1 require 'stringray/core_ext'
10 # @see StringRay::Includes#enumerate
11 # Controls how +StringRay::Includes#enumerate+ deals with whitespace.
13 # @param [Symbol] whitespace How to handle whitespace - :attach_before,
14 # :standalone, or :attach_after
15 def self.whitespace= whitespace
16 @@whitespace = whitespace
20 @@whitespace ||= :attach_before
24 # @see StringRay::Includes#enumerate
25 # Controls how +StringRay::Includes#enumerate+ deals with delemiters.
27 # @param [Symbol] delemiters How to handle delemiters - :attach_before,
28 # :standalone, or :attach_after
29 def self.delemiters= delemiters
30 @@delemiters = delemiters
34 @@delemiters ||= :attach_before
38 # @see StringRay::Word.new
39 def Word word; Word.new word; end
42 # A wrapper class for strings that are 'words' in and of themselves,
43 # composed of 'word characters'.
50 # @see StringRay::Whitespace.new
51 def Whitespace whitespace; Whitespace.new whitespace; end
54 # A wrapper class for strings that are 'whitespace' composed of 'whitespace
56 class Whitespace < String
57 Characters = [" ", "\t", "\n"]
64 # @see StringRay::Delimiter.new
65 def Delimiter delimiter; Delimiter.new delimiter; end
68 # A wrapper class for strings that are 'delimiters' composed of 'delimiter
70 class Delimiter < String
71 Characters = ['-', ',', '.', '?', '!', ':', ';', '/', '\\', '|']
78 # This is mixed into any class including +StringRay+. It exposes
79 # +::make_enumerable!+ to said class, and exposes +#to_stray+ and
80 # +#enumerate+ to said class's instances.
84 # Splits a string into an array of +StringRay+ container objects (+Word+,
85 # +Whitespace+, and +Delimiter+).
87 # @yield [element] Allows each 'element' of the string to be operated on
88 # after it is processed
89 # @yieldparam [Word, Whitespace, Delimiter] element The last processed
91 # @return [StringRay[Word, Whitespace, Delimiter]] An array of +StringRay+
96 new_element = lambda do |element|
97 yield ray.last if block_given? unless ray.empty?
101 self.scan(/./um) do |char|
102 if Delimiter::Characters.include? char
103 new_element[Delimiter.new(char)]
105 elsif Whitespace::Characters.include? char
106 if ray.last.is_a? Whitespace
109 new_element[Whitespace.new(char)]
113 if ray.last.is_a? Word
116 new_element[Word.new(char)]
132 # @see StringRay#whitespace
133 # @see StringRay#delemiters
134 # Enumerates a string, similar to +#to_stray+, but returning an array of
135 # plain +String+s instead of a +StringRay+ container object.
137 # @param [Hash] options A hash of options
138 # @yield [word] Allows each word in the string to be operated on after it is
140 # @yieldparam [String] word The last processed word
141 # @return [Array[String]] An array of words
143 def enumerate options = {}, &block
145 attach_before_next = []
147 self.to_stray do |element|
150 case options[:delemiters] || StringRay::delemiters
154 attach_before_next << element
156 if attach_before_next.empty?
158 mapped.last << element
160 attach_before_next << element
163 attach_before_next << element
168 case options[:whitespace] || StringRay::whitespace
172 attach_before_next << element
174 if attach_before_next.empty?
176 mapped.last << element
178 attach_before_next << element
181 attach_before_next << element
186 if not attach_before_next.empty?
187 mapped << [attach_before_next, element].flatten
188 attach_before_next = []
196 if not attach_before_next.empty?
197 mapped << [Word.new] unless mapped.last
198 (mapped.last << attach_before_next).flatten!
202 string = arr.map{|w|w.to_s}.join
203 yield string if block_given?
209 alias_method :each_word, :enumerate
212 # This overrides +String#each+ with +#enumerate+, thus allowing
213 # us to include +Enumerable+. Be careful, this breaks lots of existing
214 # code which depends on the old methodology of +String#each+! The
215 # overridden +String#each+ functionality will be exposed as
219 if RUBY_VERSION <= "1.9"
220 Kernel::warn "overriding String#each with StringRay#enumerate; this may break old libaries!"
221 alias_method :each_at, :each
223 alias_method :each, :enumerate
231 def self.included klass
232 klass.send :extend, Includes