epitools 0.4.49 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/TODO ADDED
@@ -0,0 +1,16 @@
1
+ ===========================
2
+ TODOs
3
+ ===========================
4
+
5
+ + Logger
6
+ |_ colourized ("ramaze" has a nice style)
7
+ |_ output to STDERR (default)
8
+ |_ no setup (default)
9
+ |_ Log "message" <- defaults to info
10
+ |_ Log.warn "message"
11
+ |_ Log object <- prettyprints it
12
+ |_ Verbose mode shows the calling method's info
13
+ |_ eg: [file:line:method]
14
+ |_ "gsmartcontrol" has good warning messages
15
+ ie: "|13<warn> |07[hz] Warning: exit: The device error log contains records of errors."
16
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.49
1
+ 0.5.0
@@ -5,22 +5,24 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epitools}
8
- s.version = "0.4.49"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["epitron"]
12
- s.date = %q{2011-06-29}
11
+ s.authors = [%q{epitron}]
12
+ s.date = %q{2011-10-13}
13
13
  s.description = %q{Miscellaneous utility libraries to make my life easier.}
14
14
  s.email = %q{chris@ill-logic.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.rdoc",
18
+ "TODO"
18
19
  ]
19
20
  s.files = [
20
21
  ".document",
21
22
  "LICENSE",
22
23
  "README.rdoc",
23
24
  "Rakefile",
25
+ "TODO",
24
26
  "VERSION",
25
27
  "epitools.gemspec",
26
28
  "lib/epitools.rb",
@@ -31,6 +33,7 @@ Gem::Specification.new do |s|
31
33
  "lib/epitools/browser/mechanize_progressbar.rb",
32
34
  "lib/epitools/clitools.rb",
33
35
  "lib/epitools/colored.rb",
36
+ "lib/epitools/ezdb.rb",
34
37
  "lib/epitools/hexdump.rb",
35
38
  "lib/epitools/its.rb",
36
39
  "lib/epitools/lcs.rb",
@@ -47,12 +50,15 @@ Gem::Specification.new do |s|
47
50
  "lib/epitools/ratio.rb",
48
51
  "lib/epitools/string_to_proc.rb",
49
52
  "lib/epitools/sys.rb",
53
+ "lib/epitools/term.rb",
54
+ "lib/epitools/trie.rb",
50
55
  "lib/epitools/zopen.rb",
51
56
  "spec/autoreq_spec.rb",
52
57
  "spec/basetypes_spec.rb",
53
58
  "spec/browser_spec.rb",
54
59
  "spec/clitools_spec.rb",
55
60
  "spec/colored_spec.rb",
61
+ "spec/ezdb_spec.rb",
56
62
  "spec/lcs_spec.rb",
57
63
  "spec/numwords_spec.rb",
58
64
  "spec/path_spec.rb",
@@ -62,12 +68,13 @@ Gem::Specification.new do |s|
62
68
  "spec/spec.opts",
63
69
  "spec/spec_helper.rb",
64
70
  "spec/sys_spec.rb",
71
+ "spec/term_spec.rb",
65
72
  "spec/zopen_spec.rb"
66
73
  ]
67
74
  s.homepage = %q{http://github.com/epitron/epitools}
68
- s.licenses = ["WTFPL"]
69
- s.require_paths = ["lib"]
70
- s.rubygems_version = %q{1.6.2}
75
+ s.licenses = [%q{WTFPL}]
76
+ s.require_paths = [%q{lib}]
77
+ s.rubygems_version = %q{1.8.6}
71
78
  s.summary = %q{NOT UTILS... METILS!}
72
79
 
73
80
  if s.respond_to? :specification_version then
@@ -82,11 +82,12 @@ require_wrapper = proc do |mod|
82
82
  end
83
83
  end
84
84
 
85
- ## Require the tools
85
+ #
86
+ # Make all the modules autoload, and require all the monkeypatches
87
+ #
86
88
  %w[
87
89
  autoloads
88
90
  basetypes
89
- niceprint
90
91
  string_to_proc
91
92
  zopen
92
93
  colored
@@ -1,4 +1,5 @@
1
1
  ## Standard library
2
+ autoload :Set, 'set'
2
3
  autoload :URI, 'uri'
3
4
  autoload :CGI, 'cgi'
4
5
  autoload :Base64, 'base64'
@@ -10,6 +11,10 @@ autoload :Tempfile, 'tempfile'
10
11
  autoload :BigDecimal, 'bigdecimal'
11
12
  autoload :StringIO, 'stringio'
12
13
  autoload :Curses, 'curses'
14
+ autoload :DateTime, 'date'
15
+ autoload :Date, 'date'
16
+ autoload :Open3, 'open3'
17
+ #autoload :DelegateClass, 'delegate'
13
18
 
14
19
  module Digest
15
20
  autoload :SHA1, 'digest/sha1'
@@ -18,11 +23,16 @@ module Digest
18
23
  end
19
24
 
20
25
  ## Nonstandard library
21
- autoload :MimeMagic, 'epitools/mimemagic'
22
26
  autoload :Path, 'epitools/path'
27
+ autoload :Ezdb, 'epitools/ezdb'
23
28
  autoload :Browser, 'epitools/browser'
24
29
  autoload :Rash, 'epitools/rash'
25
30
  autoload :Ratio, 'epitools/ratio'
26
31
  autoload :Sys, 'epitools/sys'
27
32
  autoload :ProgressBar, 'epitools/progressbar'
33
+ autoload :Trie, 'epitools/trie'
34
+ autoload :MimeMagic, 'epitools/mimemagic'
35
+ autoload :Term, 'epitools/term'
28
36
 
37
+ ## Gems
38
+ autoreq :ANSI, 'ansi'
@@ -15,6 +15,8 @@ unless defined? Enum
15
15
  end
16
16
  end
17
17
 
18
+ RbConfig = Config unless defined? RbConfig
19
+
18
20
  class Object
19
21
 
20
22
  #
@@ -32,7 +34,22 @@ class Object
32
34
  #
33
35
  # `truthy?` means `not blank?`
34
36
  #
35
- def truthy?; not blank?; end
37
+ def truthy?
38
+ if respond_to? :blank?
39
+ not blank?
40
+ else
41
+ not nil?
42
+ end
43
+ end
44
+
45
+ def marshal
46
+ Marshal.dump self
47
+ end
48
+
49
+ #
50
+ # Lets you say: `object.is_an? Array`
51
+ #
52
+ alias_method :is_an?, :is_a?
36
53
 
37
54
  end
38
55
 
@@ -44,7 +61,31 @@ class FalseClass
44
61
  def truthy?; false; end
45
62
  end
46
63
 
64
+ class Float
65
+ #
66
+ # 'true' if the float is 0.0
67
+ #
68
+ def blank?; self == 0.0; end
69
+ end
70
+
71
+ class NilClass
72
+ #
73
+ # Always 'true'; nil is considered blank.
74
+ #
75
+ def blank?; true; end
76
+ end
77
+
78
+ class Symbol
79
+ #
80
+ # Symbols are never blank.
81
+ #
82
+ def blank?; false; end
83
+ end
84
+
85
+
86
+
47
87
  class Numeric
88
+
48
89
  def integer?; true; end
49
90
 
50
91
  def truthy?; self > 0; end
@@ -53,8 +94,9 @@ class Numeric
53
94
  to_s.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
54
95
  end
55
96
 
56
- # Time
57
-
97
+ #
98
+ # Time methods
99
+ #
58
100
  {
59
101
 
60
102
  'second' => 1,
@@ -77,29 +119,95 @@ class Numeric
77
119
  def from_now
78
120
  Time.now + self
79
121
  end
122
+
80
123
  end
81
124
 
82
- class Float
125
+ class Integer
126
+
83
127
  #
84
- # 'true' if the float is 0.0
128
+ # 'true' if the integer is 0
85
129
  #
86
- def blank?; self == 0.0; end
87
- end
130
+ def blank?; self == 0; end
88
131
 
89
- class NilClass
90
132
  #
91
- # Always 'true'; nil is considered blank.
133
+ # Convert the number into a hexadecimal string representation.
134
+ # (Identical to to_s(16), except that numbers < 16 will have a 0 in front of them.)
92
135
  #
93
- def blank?; true; end
94
- end
136
+ def to_hex
137
+ "%0.2x" % self
138
+ end
139
+
140
+ #
141
+ # Convert the number to an array of bits (least significant digit first, or little-endian).
142
+ #
143
+ def to_bits
144
+ # TODO: Why does thos go into an infinite loop in 1.8.7?
145
+ ("%b" % self).chars.to_a.reverse.map(&:to_i)
146
+ end
147
+ alias_method :bits, :to_bits
148
+
149
+ #
150
+ # Cached constants for base62 encoding
151
+ #
152
+ BASE62_DIGITS = ['0'..'9', 'A'..'Z', 'a'..'z'].map(&:to_a).flatten
153
+ BASE62_BASE = BASE62_DIGITS.size
95
154
 
96
- class Symbol
97
155
  #
98
- # Symbols are never blank.
156
+ # Convert a number to a string representation (in "base62" encoding).
157
+ #
158
+ # Base62 encoding represents the number using the characters: 0..9, A..Z, a..z
99
159
  #
100
- def blank?; false; end
160
+ # It's the same scheme that url shorteners and YouTube uses for their
161
+ # ID strings. (eg: http://www.youtube.com/watch?v=dQw4w9WgXcQ)
162
+ #
163
+ def to_base62
164
+ result = []
165
+ remainder = self
166
+ max_power = ( Math.log(self) / Math.log(BASE62_BASE) ).floor
167
+
168
+ max_power.downto(0) do |power|
169
+ divisor = BASE62_BASE**power
170
+ #p [:div, divisor, :rem, remainder]
171
+ digit, remainder = remainder.divmod(divisor)
172
+ result << digit
173
+ end
174
+
175
+ result << remainder if remainder > 0
176
+
177
+ result.map{|digit| BASE62_DIGITS[digit]}.join ''
178
+ end
179
+ end
180
+
181
+
182
+ #
183
+ # Monkeypatch [] into Bignum and Fixnum using class_eval.
184
+ #
185
+ # (This is necessary because [] is defined directly on the classes, and a mixin
186
+ # module will still be overridden by Big/Fixnum's native [] method.)
187
+ #
188
+ [Bignum, Fixnum].each do |klass|
189
+
190
+ klass.class_eval do
191
+
192
+ alias_method :bit, :"[]"
193
+
194
+ #
195
+ # Extends [] so that Integers can be sliced as if they were arrays.
196
+ #
197
+ def [](arg)
198
+ case arg
199
+ when Integer
200
+ self.bit(arg)
201
+ when Range
202
+ self.bits[arg]
203
+ end
204
+ end
205
+
206
+ end
207
+
101
208
  end
102
209
 
210
+
103
211
  class String
104
212
 
105
213
  #
@@ -141,7 +249,7 @@ class String
141
249
  def tighten
142
250
  gsub(/[\t ]+/,' ').strip
143
251
  end
144
-
252
+
145
253
  #
146
254
  # Remove redundant whitespace AND newlines.
147
255
  #
@@ -149,6 +257,14 @@ class String
149
257
  gsub(/\s+/,' ').strip
150
258
  end
151
259
 
260
+ #
261
+ # Remove ANSI color codes.
262
+ #
263
+ def strip_color
264
+ gsub(/\e\[.*?(\d)+m/, '')
265
+ end
266
+ alias_method :strip_ansi, :strip_color
267
+
152
268
  #
153
269
  # Like #lines, but skips empty lines and removes \n's.
154
270
  #
@@ -157,6 +273,7 @@ class String
157
273
  split($/).select{|l| not l.blank? }
158
274
  end
159
275
 
276
+ alias_method :nicelines, :nice_lines
160
277
  alias_method :clean_lines, :nice_lines
161
278
 
162
279
  #
@@ -194,20 +311,51 @@ class String
194
311
  end
195
312
  end
196
313
 
314
+
315
+
316
+ #
317
+ # Cached constants for base62 decoding.
318
+ #
319
+ BASE62_DIGITS = Hash[ Integer::BASE62_DIGITS.map.with_index{|letter,index| [letter,index]} ]
320
+ BASE62_BASE = Integer::BASE62_BASE
321
+
322
+ #
323
+ # Convert a string (encoded in base16 "hex" -- for example, an MD5 or SHA1 hash)
324
+ # into "base62" format. (See Integer#to_base62 for more info.)
325
+ #
326
+ def to_base62
327
+ to_i(16).to_base62
328
+ end
329
+
330
+ #
331
+ # Convert a string encoded in base62 into an integer.
332
+ # (See Integer#to_base62 for more info.)
333
+ #
334
+ def from_base62
335
+ accumulator = 0
336
+ digits = chars.map { |c| BASE62_DIGITS[c] }.reverse
337
+ digits.each_with_index do |digit, power|
338
+ accumulator += (BASE62_BASE**power) * digit if digit > 0
339
+ end
340
+ accumulator
341
+ end
342
+
197
343
  #
198
344
  # Decode a mime64/base64 encoded string
199
345
  #
200
- def decode64
346
+ def from_base64
201
347
  Base64.decode64 self
202
348
  end
349
+ alias_method :decode64, :from_base64
203
350
 
204
351
  #
205
352
  # Encode into a mime64/base64 string
206
353
  #
207
- def encode64
354
+ def to_base64
208
355
  Base64.encode64 self
209
356
  end
210
- alias_method :base64, :encode64
357
+ alias_method :base64, :to_base64
358
+ alias_method :encode64, :to_base64
211
359
 
212
360
  #
213
361
  # MD5 the string
@@ -274,59 +422,16 @@ class String
274
422
  JSON.parse self
275
423
  end
276
424
 
277
- end
278
-
279
-
280
- class Integer
281
-
282
- #
283
- # 'true' if the integer is 0
284
- #
285
- def blank?; self == 0; end
286
-
287
425
  #
288
- # Convert the number into a hexadecimal string representation.
426
+ # Convert the string to a Path object.
289
427
  #
290
- def to_hex
291
- "%0.2x" % self
428
+ def as_path
429
+ Path[self]
292
430
  end
293
-
294
- #
295
- # Convert the number to an array of bits (least significant digit first, or little-endian).
296
- #
297
- def to_bits
298
- # TODO: Why does thos go into an infinite loop in 1.8.7?
299
- ("%b" % self).chars.to_a.reverse.map(&:to_i)
300
- end
301
- alias_method :bits, :to_bits
302
-
303
- end
304
-
305
-
306
- #
307
- # Monkeypatch [] into Bignum and Fixnum using class_eval.
308
- #
309
- # (This is necessary because [] is defined directly on the classes, and a mixin
310
- # module will still be overridden by Big/Fixnum's native [] method.)
311
- #
312
- [Bignum, Fixnum].each do |klass|
431
+ alias_method :to_p, :as_path
313
432
 
314
- klass.class_eval do
315
-
316
- alias_method :bit, :"[]"
317
-
318
- #
319
- # Extends [] so that Integers can be sliced as if they were arrays.
320
- #
321
- def [](arg)
322
- case arg
323
- when Integer
324
- self.bit(arg)
325
- when Range
326
- self.bits[arg]
327
- end
328
- end
329
-
433
+ def unmarshal
434
+ Marshal.restore self
330
435
  end
331
436
 
332
437
  end
@@ -392,6 +497,21 @@ class Array
392
497
  (self | other) - (self & other)
393
498
  end
394
499
 
500
+ #
501
+ # Pick a random element.
502
+ #
503
+ def pick
504
+ self[rand(size)]
505
+ end
506
+
507
+ #
508
+ # Divide the array into n pieces.
509
+ #
510
+ def / pieces
511
+ piece_size = (size.to_f / pieces).ceil
512
+ each_slice(piece_size).to_a
513
+ end
514
+
395
515
  end
396
516
 
397
517
 
@@ -417,6 +537,7 @@ module Enumerable
417
537
  # (default: false)
418
538
  # :after => true #=> split after the matched element (only has an effect when used with :include_boundary)
419
539
  # (default: false)
540
+ # :once => flase #=> only perform one split (default: false)
420
541
  #
421
542
  # Examples:
422
543
  # [1,2,3,4,5].split{ |e| e == 3 }
@@ -448,10 +569,13 @@ module Enumerable
448
569
 
449
570
  chunks = []
450
571
  current_chunk = []
572
+
573
+ splits = 0
574
+ max_splits = options[:once] == true ? 1 : options[:max_splits]
451
575
 
452
576
  each do |e|
453
577
 
454
- if boundary_test_proc.call(e)
578
+ if boundary_test_proc.call(e) and (max_splits == nil or splits < max_splits)
455
579
 
456
580
  if current_chunk.empty? and not include_boundary
457
581
  next # hit 2 boundaries in a row... just keep moving, people!
@@ -468,6 +592,8 @@ module Enumerable
468
592
  current_chunk = [] # start a new result
469
593
  current_chunk << e if include_boundary # include the boundary, if necessary
470
594
  end
595
+
596
+ splits += 1
471
597
 
472
598
  else
473
599
  current_chunk << e
@@ -507,7 +633,11 @@ module Enumerable
507
633
  # Sum the elements
508
634
  #
509
635
  def sum
510
- inject(0) { |total,n| total + n }
636
+ if block_given?
637
+ inject(0) { |total,elem| total + yield(elem) }
638
+ else
639
+ inject(0) { |total,elem| total + elem }
640
+ end
511
641
  end
512
642
 
513
643
  #
@@ -656,11 +786,12 @@ class Object
656
786
  #
657
787
  def bench(message=nil)
658
788
  start = Time.now
659
- yield
789
+ result = yield
660
790
  elapsed = Time.now - start
661
791
 
662
792
  print "[#{message}] " if message
663
- puts "elapsed time: %0.5fs" % elapsed
793
+ puts "elapsed time: %0.5fs" % elapsed
794
+ result
664
795
  end
665
796
  alias time bench
666
797
 
@@ -937,3 +1068,21 @@ def dmsg(msg)
937
1068
  end
938
1069
 
939
1070
 
1071
+ def del(x)
1072
+ case thing
1073
+ when String
1074
+ del(x.to_sym)
1075
+ when Class, Module
1076
+ Object.send(:remove_const, x)
1077
+ when Method
1078
+ x.owner.send(:undef_method, x.name)
1079
+ when Symbol
1080
+ if Object.const_get(x)
1081
+ Object.send(:remove_const, x)
1082
+ elsif method(x)
1083
+ undef_method x
1084
+ end
1085
+ else
1086
+ raise "Error: don't know how to 'del #{x.inspect}'"
1087
+ end
1088
+ end