Updated the README with more relevant data.
[stringray.git] / lib / stringray.rb
blobc0f4511e6f070a1f06de63cc07ae66bbd781acab
1 require 'stringray/includes'
3 class StringRay < Array
4   Version = 3
5   
6   @@whitespace = nil
7   @@delemiters = nil
8   
9   ##
10   # @see StringRay::Includes#enumerate
11   # @see StringRay::Includes.whitespace=
12   # Controls how +StringRay::Includes#enumerate+ deals with whitespace by default.
13   # 
14   # @param [Symbol] whitespace How to handle whitespace - :attach_before,
15   #   :standalone, or :attach_after
16   def self.whitespace= whitespace
17     @@whitespace = whitespace
18   end
19   
20   def self.whitespace
21     @@whitespace ||= :attach_before
22   end
24   ##
25   # @see StringRay::Includes#enumerate
26   # @see StringRay::Includes.delemiters=
27   # Controls how +StringRay::Includes#enumerate+ deals with delemiters by default.
28   # 
29   # @param [Symbol] delemiters How to handle delemiters - :attach_before,
30   #   :standalone, or :attach_after
31   def self.delemiters= delemiters
32     @@delemiters = delemiters
33   end
34   
35   def self.delemiters
36     @@delemiters ||= :attach_before
37   end
38   
39   # @see StringRay::Word.new
40   def self.Word word; Word.new word; end
41   
42   ##
43   # @see StringRay::Includes#to_stray
44   # @see #whitespace
45   # @see #delemiters
46   # Enumerates a string, returning an array plain +String+s.
47   # 
48   # @param [Hash] options A hash of options
49   # @yield [word] Allows each word in the string to be operated on after it is
50   #   processed
51   # @yieldparam [String] word The last processed word
52   # @return [Array[String]] An array of words
53   # @since 1
54   def enumerate options = {}, &block
55     # TODO: Can we clean this up, into a simple #inject call? I bet so.
56     # TODO: This really should return an Enumerator object. Seriously.
57     mapped = []
58     attach_before_next = []
59     
60     self.each do |element|
61       case element
62       when Delimiter
63         case options[:delemiters] || StringRay::delemiters
64         when :standalone
65           mapped << [element]
66         when :attach_after
67           attach_before_next << element
68         else
69           if attach_before_next.empty?
70             if mapped.last
71               mapped.last << element
72             else
73               attach_before_next << element
74             end
75           else
76             attach_before_next << element
77           end
78         end
79         
80       when Whitespace
81         case options[:whitespace] || StringRay::whitespace
82         when :standalone
83           mapped << [element]
84         when :attach_after
85           attach_before_next << element
86         else
87           if attach_before_next.empty?
88             if mapped.last
89               mapped.last << element
90             else
91               attach_before_next << element
92             end
93           else
94             attach_before_next << element
95           end
96         end
97         
98       when Word
99         if not attach_before_next.empty?
100           mapped << [attach_before_next, element].flatten
101           attach_before_next = []
102         else
103           mapped << [element]
104         end
105         
106       end
107     end
108     
109     if not attach_before_next.empty?
110       mapped << [Word.new] unless mapped.last
111       (mapped.last << attach_before_next).flatten!
112     end
113     
114     mapped.map do |arr|
115       string = arr.map{|w|w.to_s}.join
116       yield string if block_given?
117       string
118     end
119   end
120   
121   ##
122   # A wrapper class for strings that are 'words' in and of themselves,
123   # composed of 'word characters'.
124   class Word < String
125     def inspect
126       "(#{self})"
127     end
128   end
129   
130   # @see StringRay::Whitespace.new
131   def self.Whitespace whitespace; Whitespace.new whitespace; end
132   
133   ##
134   # A wrapper class for strings that are 'whitespace' composed of 'whitespace
135   # characters'.
136   class Whitespace < String
137     Characters = [" ", "\t", "\n"]
138     
139     def inspect
140       "#{self}"
141     end
142   end
143   
144   # @see StringRay::Delimiter.new
145   def self.Delimiter delimiter; Delimiter.new delimiter; end
146   
147   ##
148   # A wrapper class for strings that are 'delimiters' composed of 'delimiter
149   # characters'.
150   class Delimiter < String
151     Characters = ['-', ',', '.', '?', '!', ':', ';', '/', '\\', '|']
152     
153     def inspect
154       "<#{self}>"
155     end
156   end
157   
158   def inspect
159     "\"#{self.map(&:inspect).join ''}\""
160   end
161