extensions 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ #!/usr/local/bin/ruby -w
2
+ #
3
+ # == extensions/hash.rb
4
+ #
5
+ # Adds methods to the builtin Hash class.
6
+ #
7
+
8
+ require "extensions/_base"
9
+
10
+ #
11
+ # * Hash#select!
12
+ #
13
+ ExtensionsProject.implement(Hash, :select!) do
14
+ class Hash
15
+ #
16
+ # In-place version of Hash#select. (Counterpart to, and opposite of, the
17
+ # built-in #reject!)
18
+ #
19
+ def select!
20
+ reject! { |k,v| not yield(k,v) }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # == extensions/io.rb
5
+ #
6
+ # Adds methods to the builtin IO class.
7
+ #
8
+
9
+ require "extensions/_base"
10
+
11
+ # This is Ruby's built-in IO class.
12
+ class IO
13
+ end
14
+
15
+ #
16
+ # * IO.write
17
+ #
18
+ ExtensionsProject.implement(IO, :write, :class) do
19
+ class << IO
20
+ #
21
+ # Writes the given data to the given path and closes the file. This is
22
+ # done in binary mode, complementing <tt>IO.read</tt> in standard Ruby.
23
+ #
24
+ # Returns the number of bytes written.
25
+ #
26
+ def write(path, data)
27
+ File.open(path, "wb") do |file|
28
+ return file.write(data)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ # * IO.writelines
36
+ #
37
+ ExtensionsProject.implement(IO, :writelines, :class) do
38
+ class << IO
39
+ #
40
+ # Writes the given array of data to the given path and closes the file.
41
+ # This is done in binary mode, complementing <tt>IO.readlines</tt> in
42
+ # standard Ruby.
43
+ #
44
+ # Note that +readlines+ (the standard Ruby method) returns an array of lines
45
+ # <em>with newlines intact</em>, whereas +writelines+ uses +puts+, and so
46
+ # appends newlines if necessary. In this small way, +readlines+ and
47
+ # +writelines+ are not exact opposites.
48
+ #
49
+ # Returns +nil+.
50
+ #
51
+ def writelines(path, data)
52
+ File.open(path, "wb") do |file|
53
+ file.puts(data)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,204 @@
1
+ #!/usr/local/bin/ruby -w
2
+ #
3
+ # == extensions/integer.rb
4
+ #
5
+ # Adds methods to the builtin Numeric and Integer classes.
6
+ #
7
+
8
+ require "extensions/_base"
9
+
10
+ #
11
+ # * Integer#even?
12
+ #
13
+ ExtensionsProject.implement(Integer, :even?) do
14
+ class Integer
15
+ #
16
+ # Returns true if this integer is even, false otherwise.
17
+ # 14.even? # -> true
18
+ # 15.even? # -> false
19
+ #
20
+ def even?
21
+ self % 2 == 0
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ #
28
+ # * Integer#odd?
29
+ #
30
+ ExtensionsProject.implement(Integer, :odd?) do
31
+ class Integer
32
+ #
33
+ # Returns true if this integer is odd, false otherwise.
34
+ # -99.odd? # -> true
35
+ # -98.odd? # -> false
36
+ #
37
+ def odd?
38
+ self % 2 == 1
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ ExtensionsProject.implement(Numeric, :format_s) do
45
+ #--
46
+ # Copyright � 2003 Austin Ziegler
47
+ #
48
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ # of this software and associated documentation files (the "Software"), to
50
+ # deal in the Software without restriction, including without limitation the
51
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
52
+ # sell copies of the Software, and to permit persons to whom the Software is
53
+ # furnished to do so, subject to the following conditions:
54
+ #
55
+ # The above copyright notice and this permission notice shall be included in
56
+ # all copies or substantial portions of the Software.
57
+ #
58
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
63
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
64
+ # IN THE SOFTWARE.
65
+ #++
66
+ class Numeric
67
+ #
68
+ # Provides the base formatting styles for #format_s. See #format_s for
69
+ # more details. Two keys provided that are not supported in the
70
+ # #format_s arguments are:
71
+ #
72
+ # <tt>:style</tt>:: Allows a style to inherit from other styles. Styles
73
+ # will be applied in oldest-first order in the event
74
+ # of multiple inheritance layers.
75
+ # <tt>:id</tt>:: This must be provided on any default style created
76
+ # or provided so as to provide a stop marker so that
77
+ # recursive styles do not result in an infinite loop.
78
+ #
79
+ # This is an implementation detail, not important for users of the class.
80
+ #
81
+ FORMAT_STYLES = {
82
+ :us => { :sep => ',', :dec => '.', :id => :us },
83
+ :usd => { :style => :us, :currency => { :id => "$", :pos => :before }, :id => :usd },
84
+ :eu => { :sep => ' ', :dec => ',', :id => :us },
85
+ :euro => { :style => :eu, :currency => { :id => "�", :pos => :before }, :id => :euro },
86
+ :percent => { :style => :us, :currency => { :id => "%%", :pos => :after }, :id => :percent }
87
+ }
88
+
89
+ #
90
+ # Format a number as a string, using US or European conventions, and
91
+ # allowing for the accounting format of representing negative numbers.
92
+ # Optionally, currency formatting options can be provided.
93
+ #
94
+ # For example:
95
+ # x = -10259.8937
96
+ # x.format_s # => "-10,259.8937"
97
+ # x.format_s(:us) # => "-10,259.8937"
98
+ # x.format_s(:usd) # => "$-10,259.8937"
99
+ # x.format_s(:eu) # => "-10 259,8937"
100
+ # x.format_s(:euro) # => "�-10 259,8937"
101
+ # x.format_s(:us, :acct => true) # => "(10,259.8937)"
102
+ # x.format_s(:eu, :acct => true) # => "(10 259,8937)"
103
+ # x.format_s(:usd, :acct => true) # => "$(10,259.8937)"
104
+ # x.format_s(:euro, :acct => true) # => "�(10 259,8937)"
105
+ # x.format_s(:percent) # => "-10,259.8937%"
106
+ #
107
+ # You may configure several aspects of the formatting by providing keyword
108
+ # arguments after the country and accounting arguments. One example of that
109
+ # is the :acct keyword. A more insane example is:
110
+ #
111
+ # x = -10259.8937
112
+ # x.format_s(:us,
113
+ # :sep => ' ', :dec => ',',
114
+ # :neg => '<%s>', :size => 2,
115
+ # :fd => true) # -> "<1 02 59,89 37>"
116
+ #
117
+ # The keyword parameters are as follows:
118
+ #
119
+ # <tt>:acct</tt>:: If +true+, then use accounting style for negative
120
+ # numbers. This overrides any value for
121
+ # <tt>:neg</tt>.
122
+ # <tt>:sep</tt>:: Default "," for US, " " for Euro. Separate the
123
+ # number groups from each other with this string.
124
+ # <tt>:dec</tt>:: Default "." for US, "," for Euro. Separate the
125
+ # number's integer part from the fractional part
126
+ # with this string.
127
+ # <tt>:neg</tt>:: Default <tt>"-%s"</tt>. The format string used to
128
+ # represent negative numbers. If <tt>:acct</tt> is
129
+ # +true+, this is set to <tt>"(%s)"</tt>.
130
+ # <tt>:size</tt>:: The number of digits per group. Defaults to
131
+ # thousands (3).
132
+ # <tt>:fd</tt>:: Indicates whether the decimal portion of the
133
+ # number should be formatted the same way as the
134
+ # integer portion of the number. ("fd" == "format
135
+ # decimal".) Defaults to +false+.
136
+ # <tt>:currency</tt>:: This is an optional hash with two keys,
137
+ # <tt>:id</tt> and <tt>:pos</tt>. <tt>:id</tt> is
138
+ # the string value of the currency (e.g.,
139
+ # <tt>"$"</tt>, <tt>"�"</tt>, <tt>"USD&nbsp;"</tt>);
140
+ # <tt>:pos</tt> is either <tt>:before</tt> or
141
+ # <tt>:after</tt>, referring to the position of the
142
+ # currency indicator. The default <tt>:pos</tt> is
143
+ # <tt>:before</tt>.
144
+ #
145
+ def format_s(style = :us, configs={})
146
+ style = FORMAT_STYLES[style].dup # Adopt US style by default.
147
+
148
+ # Deal with recursive styles.
149
+ if style[:style]
150
+ styles = []
151
+ s = style
152
+ while s[:style]
153
+ s = FORMAT_STYLES[s[:style]].dup
154
+ styles << s
155
+ break if s[:style] = s[:id]
156
+ end
157
+ styles.reverse_each { |s| style.merge!(s) }
158
+ end
159
+ # Merge the configured style.
160
+ style.merge!(configs)
161
+
162
+ sm = style[:sep] || ','
163
+ dp = style[:dec] || '.'
164
+ if style[:acct]
165
+ fmt = '(%s)'
166
+ else
167
+ fmt = style[:neg] || '-%s'
168
+ end
169
+ sz = style[:size] || 3
170
+ format_decimal = style[:fd]
171
+ ng = (self < 0)
172
+ fmt = "%s" if not ng
173
+
174
+ dec, frac = self.abs.to_s.split(/\./)
175
+
176
+ dec.reverse!
177
+ dec.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
178
+ dec.gsub!(/#{sm}$/, '')
179
+ dec.reverse!
180
+
181
+ if format_decimal and not frac.nil?
182
+ frac.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
183
+ frac.gsub!(/#{sm}$/, '')
184
+ end
185
+
186
+ if frac.nil?
187
+ val = dec
188
+ else
189
+ val = "#{dec}#{dp}#{frac}"
190
+ end
191
+
192
+ if style[:currency]
193
+ if style[:currency][:pos].nil? or style[:currency][:pos] == :before
194
+ fmt = "#{style[:currency][:id]}#{fmt}"
195
+ elsif style[:currency][:pos] == :after
196
+ fmt = "#{fmt}#{style[:currency][:id]}"
197
+ end
198
+ end
199
+
200
+ fmt % val
201
+ end
202
+ end # class Numeric
203
+ end # ExtensionsProject.implement
204
+
@@ -0,0 +1,164 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # == extensions/object.rb
5
+ #
6
+ # Adds methods to the builtin Object class.
7
+ #
8
+
9
+ require 'extensions/_base'
10
+
11
+
12
+ #
13
+ # Object#singleton_class
14
+ #
15
+ ExtensionsProject.implement(Object, :singleton_class) do
16
+ class Object
17
+ #
18
+ # Returns the singleton class associated with this object. How useful this
19
+ # is I don't know, but it's an idiom that has appeared on ruby-talk several
20
+ # times.
21
+ #
22
+ def singleton_class
23
+ class << self
24
+ self
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+
31
+ #
32
+ # * Object.in?
33
+ # This has special treatment: it's included here and in enumerable.rb, so we don't
34
+ # want a warning if it's already defined.
35
+ #
36
+ unless Object.method_defined?(:in?)
37
+ ExtensionsProject.implement(Object, :in?) do
38
+ class Object
39
+ #
40
+ # Test this object for inclusion in a given collection.
41
+ #
42
+ # 45.in? (1...100) => true
43
+ #
44
+ # This method is contained in <tt>object.rb</tt> and
45
+ # <tt>enumerable.rb</tt>, because it logically belongs in both.
46
+ #
47
+ def in?(enumerable)
48
+ enumerable.include?(self)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+
55
+ #
56
+ # * Object.not_nil?
57
+ #
58
+ ExtensionsProject.implement(Object, :not_nil?) do
59
+ class Object
60
+ #
61
+ # The opposite of <tt>#nil?</tt>.
62
+ #
63
+ # "hello".not_nil? # -> true
64
+ # nil.not_nil? # -> false
65
+ #
66
+ def not_nil?
67
+ not self.nil?
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ #
74
+ # * Object.non_nil?
75
+ #
76
+ ExtensionsProject.implement(Object, :non_nil?) do
77
+ class Object
78
+ #
79
+ # The opposite of <tt>#nil?</tt>.
80
+ #
81
+ # "hello".non_nil? # -> true
82
+ # nil.non_nil? # -> false
83
+ #
84
+ def non_nil?
85
+ not self.nil?
86
+ end
87
+ end
88
+ end
89
+
90
+
91
+ #
92
+ # Object#pp_s
93
+ #
94
+ ExtensionsProject.implement(Object, :pp_s) do
95
+ require 'pp'
96
+ require 'stringio'
97
+ class Object
98
+ #
99
+ # Returns a pretty-printed string of the object. Requires libraries +pp+ and
100
+ # +stringio+ from the Ruby standard library.
101
+ #
102
+ # The following code pretty-prints an object (much like +p+ plain-prints an
103
+ # object):
104
+ #
105
+ # pp object
106
+ #
107
+ # The following code captures the pretty-printing in +str+ instead of
108
+ # sending it to +STDOUT+.
109
+ #
110
+ # str = object.pp_s
111
+ #
112
+ def pp_s
113
+ pps = StringIO.new
114
+ PP.pp(self, pps)
115
+ pps.string
116
+ end
117
+ end
118
+ end
119
+
120
+ #
121
+ # Object#pp_s
122
+ #
123
+ ExtensionsProject.implement(Object, :define_method) do
124
+ class Object
125
+ #
126
+ # Defines a singleton method on the object. For example, the following are
127
+ # equivalent (assume <tt>o = Object.new</tt>):
128
+ #
129
+ # def o.add(x, y)
130
+ # x + y
131
+ # end
132
+ #
133
+ # o.define_method(:add) do |x, y|
134
+ # x + y
135
+ # end
136
+ #
137
+ # The difference is that with <tt>define_method</tt>, you can use variables
138
+ # local to the _current_ scope.
139
+ #
140
+ # x = 5
141
+ # o.define_method(:add_x) do |n|
142
+ # x + n
143
+ # end
144
+ # o.add_x(11) # -> 16
145
+ #
146
+ # You can't define such a method as <tt>add_x</tt> above with <tt>def
147
+ # o.add_x; x + n; end</tt>, as +def+ introduces a new scope.
148
+ #
149
+ # There are three ways to provide the body of the method: with a block (as
150
+ # in both examples above), or with a +Proc+ or +Method+ object. See the
151
+ # built-in method <tt>Module#define_method</tt> for details.
152
+ #
153
+ # (This method is exactly equivalent to calling <tt>Module#define_method</tt>
154
+ # in the scope of the singleton class of the object.)
155
+ #
156
+ def define_method(*args, &block)
157
+ singleton_class = class << self; self; end
158
+ singleton_class.module_eval do
159
+ define_method(*args, &block)
160
+ end
161
+ end
162
+ end
163
+ end
164
+