extensions 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,316 +1,316 @@
1
- #!/usr/local/bin/ruby -w
2
-
3
- #
4
- # == extensions/string.rb
5
- #
6
- # Adds methods to the builtin String class.
7
- #
8
-
9
- require "extensions/_base"
10
-
11
-
12
- ExtensionsProject.implement(String, :leftmost_indent) do
13
- class String
14
- #
15
- # Returns the size of the smallest indent of any line in the string.
16
- # Emits a warning if tabs are found, and if <tt>$VERBOSE</tt> is on.
17
- # You can use #expand_tabs to avoid this. This method is primarily intended
18
- # for use by #tabto and is not likely to be all that useful in its own
19
- # right.
20
- #
21
- def leftmost_indent
22
- tabs_found = false
23
- scan(/^([ \t]*)\S/).flatten.map { |ws|
24
- tabs_found = true if ws =~ /\t/
25
- ws.size
26
- }.compact.min
27
- ensure
28
- if tabs_found and $VERBOSE
29
- $stderr.puts %{
30
- String#leftmost_indent: warning: tabs treated as spaces
31
- (value: #{self.inspect[0..30]}...")
32
- }.strip
33
- end
34
- end
35
- protected :leftmost_indent
36
- end
37
- end
38
-
39
-
40
- ExtensionsProject.implement(String, :expand_tabs) do
41
- class String
42
- #
43
- # Expands tabs to +n+ spaces. Non-destructive. If +n+ is 0, then tabs are
44
- # simply removed. Raises an exception if +n+ is negative.
45
- #
46
- #--
47
- # Thanks to GGaramuno for a more efficient algorithm. Very nice.
48
- def expand_tabs(n=8)
49
- n = n.to_int
50
- raise ArgumentError, "n must be >= 0" if n < 0
51
- return gsub(/\t/, "") if n == 0
52
- return gsub(/\t/, " ") if n == 1
53
- str = self.dup
54
- while
55
- str.gsub!(/^([^\t\n]*)(\t+)/) { |f|
56
- val = ( n * $2.size - ($1.size % n) )
57
- $1 << (' ' * val)
58
- }
59
- end
60
- str
61
- end
62
- end
63
- end
64
-
65
-
66
- ExtensionsProject.implement(String, :indent) do
67
- class String
68
- #
69
- # Indents the string +n+ spaces.
70
- #
71
- def indent(n)
72
- n = n.to_int
73
- return outdent(-n) if n < 0
74
- gsub(/^/, " "*n)
75
- end
76
- end
77
- end
78
-
79
-
80
- ExtensionsProject.implement(String, :outdent) do
81
- class String
82
- #
83
- # Outdents the string +n+ spaces. Initial tabs will cause problems and
84
- # cause a warning to be emitted (if warnings are on). Relative indendation
85
- # is always preserved. Once the block hits the beginning of the line,
86
- # that's it. In the following example, <tt>.</tt> represents space from the
87
- # beginning of the line.
88
- #
89
- # str = %{
90
- # ..One
91
- # ....Two
92
- # }.outdent(4)
93
- #
94
- # is
95
- #
96
- # One
97
- # ..Two
98
- #
99
- def outdent(n)
100
- n = n.to_int
101
- return indent(-n) if n < 0
102
- tabto(leftmost_indent - n)
103
- end
104
- end
105
- end
106
-
107
-
108
- ExtensionsProject.implement(String, :tabto) do
109
- class String
110
- #
111
- # Move the string to the <tt>n</tt>th column. Relative indentation is preserved.
112
- # Column indices begin at 0, so the result is that the leftmost character of
113
- # the string has +n+ spaces before it.
114
- #
115
- # Examples:
116
- # "xyz".tabto(0) # -> "xyz"
117
- # "xyz".tabto(1) # -> " xyz"
118
- # "xyz".tabto(2) # -> " xyz"
119
- # " xyz".tabto(1) # -> " xyz"
120
- #
121
- # str = <<EOF
122
- # Hello, my name
123
- # is Gerald.
124
- # EOF
125
- # str.tabto(5) == <<EOF # -> true
126
- # Hello, my name
127
- # is Gerald.
128
- # EOF
129
- #
130
- def tabto(n)
131
- n = n.to_int
132
- n = 0 if n < 0
133
- find = " " * leftmost_indent()
134
- replace = " " * (n)
135
- gsub(/^#{find}/, replace)
136
- end
137
- end
138
- end
139
-
140
-
141
- ExtensionsProject.implement(String, :taballto) do
142
- class String
143
- #
144
- # Tabs all lines in the string to column +n+. That is, relative indentation
145
- # is _not_ preserved.
146
- #
147
- def taballto(n)
148
- n = n.to_int
149
- n = 0 if n < 0
150
- gsub(/^[ \t]*/, " "*n)
151
- end
152
- end
153
- end
154
-
155
-
156
- ExtensionsProject.implement(String, :trim) do
157
- class String
158
- #
159
- # Trims a string:
160
- # - removes one initial blank line
161
- # - removes trailing spaces on each line
162
- # - if +margin+ is given, removes initial spaces up to and including
163
- # the margin on each line, plus one space
164
- #
165
- # This is designed specifically for working with inline documents.
166
- # Here-documents are great, except they tend to go against the indentation
167
- # of your code. This method allows a convenient way of using %{}-style
168
- # documents. For instance:
169
- #
170
- # USAGE = %{
171
- # | usage: prog [-o dir] -h file...
172
- # | where
173
- # | -o dir outputs to DIR
174
- # | -h prints this message
175
- # }.trim("|")
176
- #
177
- # # USAGE == "usage: prog [-o dir] -h file...\n where"...
178
- # # (note single space to right of margin is deleted)
179
- #
180
- # Note carefully that if no margin string is given, then there is no
181
- # clipping at the beginning of each line and your string will remain
182
- # indented. You can use <tt>tabto(0)</tt> to align it with the left of
183
- # screen (while preserving relative indentation).
184
- #
185
- # USAGE = %{
186
- # usage: prog [-o dir] -h file...
187
- # where
188
- # -o dir outputs to DIR
189
- # -h prints this message
190
- # }.trim.tabto(0)
191
- #
192
- # # USAGE == (same as last example)
193
- #
194
- def trim(margin=nil)
195
- s = self.dup
196
- # Remove initial blank line.
197
- s.sub!(/\A[ \t]*\n/, "")
198
- # Get rid of the margin, if it's specified.
199
- unless margin.nil?
200
- margin_re = Regexp.escape(margin || "")
201
- margin_re = /^[ \t]*#{margin_re} ?/
202
- s.gsub!(margin_re, "")
203
- end
204
- # Remove trailing whitespace on each line
205
- s.gsub!(/[ \t]+$/, "")
206
- s
207
- end
208
- end
209
- end
210
-
211
-
212
- ExtensionsProject.implement(String, :starts_with?) do
213
- class String
214
- #
215
- # Returns true iff this string starts with +str+.
216
- # "Hello, world".starts_with?("He") # -> true
217
- # "Hello, world".starts_with?("Green") # -> false
218
- #
219
- def starts_with?(str)
220
- str = str.to_str
221
- head = self[0, str.length]
222
- head == str
223
- end
224
- end
225
- end
226
-
227
-
228
- ExtensionsProject.implement(String, :ends_with?) do
229
- class String
230
- #
231
- # Returns true iff this string ends with +str+.
232
- # "Hello, world".ends_with?(", world") # -> true
233
- # "Hello, world".ends_with?("Green") # -> false
234
- #
235
- def ends_with?(str)
236
- str = str.to_str
237
- tail = self[-str.length, str.length]
238
- tail == str
239
- end
240
- end
241
- end
242
-
243
-
244
- ExtensionsProject.implement(String, :line) do
245
- class String
246
- #
247
- # Returns a line or lines from the string. +args+ can be a single integer,
248
- # two integers or a range, as per <tt>Array#slice</tt>. The return value is
249
- # a single String (a single line), an array of Strings (multiple lines) or
250
- # +nil+ (out of bounds). Note that lines themselves do not contain a
251
- # trailing newline character; that is metadata. Indexes out of bounds are
252
- # ignored.
253
- #
254
- # data = " one \n two \n three \n four \n five \n"
255
- # data.line(1) # -> " two "
256
- # data.line(0,1) # -> [" one "]
257
- # data.line(3..9) # -> [" four ", " five "]
258
- # data.line(9) # -> nil
259
- #
260
- def line(*args)
261
- self.split(/\n/).slice(*args)
262
- rescue TypeError
263
- raise TypeError,
264
- "String#line(*args): args must be one Integer, two Integers or a Range"
265
- rescue ArgumentError
266
- raise ArgumentError,
267
- "String#line(*args): args must be one Integer, two Integers or a Range"
268
- end
269
- end
270
- end
271
-
272
-
273
- ExtensionsProject.implement(String, :cmp) do
274
- class String
275
- #
276
- # Compare this string to +other+, returning the first index at which they
277
- # differ, or +nil+ if they are equal.
278
- #
279
- # "practise".cmp("practice") # -> 6
280
- # "noun".cmp("nouns") # -> 5 (and vice versa)
281
- # "fly".cmp("fly") # -> nil
282
- #
283
- def cmp(other)
284
- other = other.to_str
285
- if self == other
286
- return nil
287
- else
288
- n = [self.size, other.size].min
289
- (0..n).each do |i|
290
- return i unless self[i] == other[i]
291
- end
292
- end
293
- end
294
- end
295
- end
296
-
297
- ExtensionsProject.implement(String, :join) do
298
- class String
299
- #
300
- # Join all the lines of the string together, and compress spaces. The resulting string
301
- # will have no surrounding whitespace.
302
- #
303
- # text = %{
304
- # Once upon a time,
305
- # Little Red Riding Hood ...
306
- #
307
- # }
308
- #
309
- # text.join # -> "Once upon a time, Little Red Riding Hood ..."
310
- #
311
- def join
312
- gsub(/([ \t]*\n[ \t]*)+/, ' ').strip
313
- end
314
- end
315
- end
316
-
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ #
4
+ # == extensions/string.rb
5
+ #
6
+ # Adds methods to the builtin String class.
7
+ #
8
+
9
+ require "extensions/_base"
10
+
11
+
12
+ ExtensionsProject.implement(String, :leftmost_indent) do
13
+ class String
14
+ #
15
+ # Returns the size of the smallest indent of any line in the string.
16
+ # Emits a warning if tabs are found, and if <tt>$VERBOSE</tt> is on.
17
+ # You can use #expand_tabs to avoid this. This method is primarily intended
18
+ # for use by #tabto and is not likely to be all that useful in its own
19
+ # right.
20
+ #
21
+ def leftmost_indent
22
+ tabs_found = false
23
+ scan(/^([ \t]*)\S/).flatten.map { |ws|
24
+ tabs_found = true if ws =~ /\t/
25
+ ws.size
26
+ }.compact.min
27
+ ensure
28
+ if tabs_found and $VERBOSE
29
+ $stderr.puts %{
30
+ String#leftmost_indent: warning: tabs treated as spaces
31
+ (value: #{self.inspect[0..30]}...")
32
+ }.strip
33
+ end
34
+ end
35
+ protected :leftmost_indent
36
+ end
37
+ end
38
+
39
+
40
+ ExtensionsProject.implement(String, :expand_tabs) do
41
+ class String
42
+ #
43
+ # Expands tabs to +n+ spaces. Non-destructive. If +n+ is 0, then tabs are
44
+ # simply removed. Raises an exception if +n+ is negative.
45
+ #
46
+ #--
47
+ # Thanks to GGaramuno for a more efficient algorithm. Very nice.
48
+ def expand_tabs(n=8)
49
+ n = n.to_int
50
+ raise ArgumentError, "n must be >= 0" if n < 0
51
+ return gsub(/\t/, "") if n == 0
52
+ return gsub(/\t/, " ") if n == 1
53
+ str = self.dup
54
+ while
55
+ str.gsub!(/^([^\t\n]*)(\t+)/) { |f|
56
+ val = ( n * $2.size - ($1.size % n) )
57
+ $1 << (' ' * val)
58
+ }
59
+ end
60
+ str
61
+ end
62
+ end
63
+ end
64
+
65
+
66
+ ExtensionsProject.implement(String, :indent) do
67
+ class String
68
+ #
69
+ # Indents the string +n+ spaces.
70
+ #
71
+ def indent(n)
72
+ n = n.to_int
73
+ return outdent(-n) if n < 0
74
+ gsub(/^/, " "*n)
75
+ end
76
+ end
77
+ end
78
+
79
+
80
+ ExtensionsProject.implement(String, :outdent) do
81
+ class String
82
+ #
83
+ # Outdents the string +n+ spaces. Initial tabs will cause problems and
84
+ # cause a warning to be emitted (if warnings are on). Relative indendation
85
+ # is always preserved. Once the block hits the beginning of the line,
86
+ # that's it. In the following example, <tt>.</tt> represents space from the
87
+ # beginning of the line.
88
+ #
89
+ # str = %{
90
+ # ..One
91
+ # ....Two
92
+ # }.outdent(4)
93
+ #
94
+ # is
95
+ #
96
+ # One
97
+ # ..Two
98
+ #
99
+ def outdent(n)
100
+ n = n.to_int
101
+ return indent(-n) if n < 0
102
+ tabto(leftmost_indent - n)
103
+ end
104
+ end
105
+ end
106
+
107
+
108
+ ExtensionsProject.implement(String, :tabto) do
109
+ class String
110
+ #
111
+ # Move the string to the <tt>n</tt>th column. Relative indentation is preserved.
112
+ # Column indices begin at 0, so the result is that the leftmost character of
113
+ # the string has +n+ spaces before it.
114
+ #
115
+ # Examples:
116
+ # "xyz".tabto(0) # -> "xyz"
117
+ # "xyz".tabto(1) # -> " xyz"
118
+ # "xyz".tabto(2) # -> " xyz"
119
+ # " xyz".tabto(1) # -> " xyz"
120
+ #
121
+ # str = <<EOF
122
+ # Hello, my name
123
+ # is Gerald.
124
+ # EOF
125
+ # str.tabto(5) == <<EOF # -> true
126
+ # Hello, my name
127
+ # is Gerald.
128
+ # EOF
129
+ #
130
+ def tabto(n)
131
+ n = n.to_int
132
+ n = 0 if n < 0
133
+ find = " " * leftmost_indent()
134
+ replace = " " * (n)
135
+ gsub(/^#{find}/, replace)
136
+ end
137
+ end
138
+ end
139
+
140
+
141
+ ExtensionsProject.implement(String, :taballto) do
142
+ class String
143
+ #
144
+ # Tabs all lines in the string to column +n+. That is, relative indentation
145
+ # is _not_ preserved.
146
+ #
147
+ def taballto(n)
148
+ n = n.to_int
149
+ n = 0 if n < 0
150
+ gsub(/^[ \t]*/, " "*n)
151
+ end
152
+ end
153
+ end
154
+
155
+
156
+ ExtensionsProject.implement(String, :trim) do
157
+ class String
158
+ #
159
+ # Trims a string:
160
+ # - removes one initial blank line
161
+ # - removes trailing spaces on each line
162
+ # - if +margin+ is given, removes initial spaces up to and including
163
+ # the margin on each line, plus one space
164
+ #
165
+ # This is designed specifically for working with inline documents.
166
+ # Here-documents are great, except they tend to go against the indentation
167
+ # of your code. This method allows a convenient way of using %{}-style
168
+ # documents. For instance:
169
+ #
170
+ # USAGE = %{
171
+ # | usage: prog [-o dir] -h file...
172
+ # | where
173
+ # | -o dir outputs to DIR
174
+ # | -h prints this message
175
+ # }.trim("|")
176
+ #
177
+ # # USAGE == "usage: prog [-o dir] -h file...\n where"...
178
+ # # (note single space to right of margin is deleted)
179
+ #
180
+ # Note carefully that if no margin string is given, then there is no
181
+ # clipping at the beginning of each line and your string will remain
182
+ # indented. You can use <tt>tabto(0)</tt> to align it with the left of
183
+ # screen (while preserving relative indentation).
184
+ #
185
+ # USAGE = %{
186
+ # usage: prog [-o dir] -h file...
187
+ # where
188
+ # -o dir outputs to DIR
189
+ # -h prints this message
190
+ # }.trim.tabto(0)
191
+ #
192
+ # # USAGE == (same as last example)
193
+ #
194
+ def trim(margin=nil)
195
+ s = self.dup
196
+ # Remove initial blank line.
197
+ s.sub!(/\A[ \t]*\n/, "")
198
+ # Get rid of the margin, if it's specified.
199
+ unless margin.nil?
200
+ margin_re = Regexp.escape(margin || "")
201
+ margin_re = /^[ \t]*#{margin_re} ?/
202
+ s.gsub!(margin_re, "")
203
+ end
204
+ # Remove trailing whitespace on each line
205
+ s.gsub!(/[ \t]+$/, "")
206
+ s
207
+ end
208
+ end
209
+ end
210
+
211
+
212
+ ExtensionsProject.implement(String, :starts_with?) do
213
+ class String
214
+ #
215
+ # Returns true iff this string starts with +str+.
216
+ # "Hello, world".starts_with?("He") # -> true
217
+ # "Hello, world".starts_with?("Green") # -> false
218
+ #
219
+ def starts_with?(str)
220
+ str = str.to_str
221
+ head = self[0, str.length]
222
+ head == str
223
+ end
224
+ end
225
+ end
226
+
227
+
228
+ ExtensionsProject.implement(String, :ends_with?) do
229
+ class String
230
+ #
231
+ # Returns true iff this string ends with +str+.
232
+ # "Hello, world".ends_with?(", world") # -> true
233
+ # "Hello, world".ends_with?("Green") # -> false
234
+ #
235
+ def ends_with?(str)
236
+ str = str.to_str
237
+ tail = self[-str.length, str.length]
238
+ tail == str
239
+ end
240
+ end
241
+ end
242
+
243
+
244
+ ExtensionsProject.implement(String, :line) do
245
+ class String
246
+ #
247
+ # Returns a line or lines from the string. +args+ can be a single integer,
248
+ # two integers or a range, as per <tt>Array#slice</tt>. The return value is
249
+ # a single String (a single line), an array of Strings (multiple lines) or
250
+ # +nil+ (out of bounds). Note that lines themselves do not contain a
251
+ # trailing newline character; that is metadata. Indexes out of bounds are
252
+ # ignored.
253
+ #
254
+ # data = " one \n two \n three \n four \n five \n"
255
+ # data.line(1) # -> " two "
256
+ # data.line(0,1) # -> [" one "]
257
+ # data.line(3..9) # -> [" four ", " five "]
258
+ # data.line(9) # -> nil
259
+ #
260
+ def line(*args)
261
+ self.split(/\n/).slice(*args)
262
+ rescue TypeError
263
+ raise TypeError,
264
+ "String#line(*args): args must be one Integer, two Integers or a Range"
265
+ rescue ArgumentError
266
+ raise ArgumentError,
267
+ "String#line(*args): args must be one Integer, two Integers or a Range"
268
+ end
269
+ end
270
+ end
271
+
272
+
273
+ ExtensionsProject.implement(String, :cmp) do
274
+ class String
275
+ #
276
+ # Compare this string to +other+, returning the first index at which they
277
+ # differ, or +nil+ if they are equal.
278
+ #
279
+ # "practise".cmp("practice") # -> 6
280
+ # "noun".cmp("nouns") # -> 5 (and vice versa)
281
+ # "fly".cmp("fly") # -> nil
282
+ #
283
+ def cmp(other)
284
+ other = other.to_str
285
+ if self == other
286
+ return nil
287
+ else
288
+ n = [self.size, other.size].min
289
+ (0..n).each do |i|
290
+ return i unless self[i] == other[i]
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ ExtensionsProject.implement(String, :join) do
298
+ class String
299
+ #
300
+ # Join all the lines of the string together, and compress spaces. The resulting string
301
+ # will have no surrounding whitespace.
302
+ #
303
+ # text = %{
304
+ # Once upon a time,
305
+ # Little Red Riding Hood ...
306
+ #
307
+ # }
308
+ #
309
+ # text.join # -> "Once upon a time, Little Red Riding Hood ..."
310
+ #
311
+ def join
312
+ gsub(/([ \t]*\n[ \t]*)+/, ' ').strip
313
+ end
314
+ end
315
+ end
316
+
@@ -1,28 +1,28 @@
1
- #!/usr/local/bin/ruby -w
2
- #
3
- # == extensions/symbol.rb
4
- #
5
- # Adds methods to the builtin Symbol class.
6
- #
7
-
8
- require "extensions/_base"
9
-
10
-
11
- #
12
- # * Symbol#to_proc
13
- #
14
- ExtensionsProject.implement(Symbol, :to_proc) do
15
- class Symbol
16
- #
17
- # Allows a Symbol to be implicitly converted to a Proc.
18
- #
19
- # This allows such conveniences as:
20
- # %{john terry fiona}.map(&:capitalize) # -> %{John Terry Fiona}
21
- # sum = numbers.inject(&:+)
22
- #
23
- def to_proc
24
- proc { |obj, *args| obj.send(self, *args) }
25
- end
26
- end
27
- end
28
-
1
+ #!/usr/local/bin/ruby -w
2
+ #
3
+ # == extensions/symbol.rb
4
+ #
5
+ # Adds methods to the builtin Symbol class.
6
+ #
7
+
8
+ require "extensions/_base"
9
+
10
+
11
+ #
12
+ # * Symbol#to_proc
13
+ #
14
+ ExtensionsProject.implement(Symbol, :to_proc) do
15
+ class Symbol
16
+ #
17
+ # Allows a Symbol to be implicitly converted to a Proc.
18
+ #
19
+ # This allows such conveniences as:
20
+ # %{john terry fiona}.map(&:capitalize) # -> %{John Terry Fiona}
21
+ # sum = numbers.inject(&:+)
22
+ #
23
+ def to_proc
24
+ proc { |obj, *args| obj.send(self, *args) }
25
+ end
26
+ end
27
+ end
28
+