buzzcorej 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "buzzcorej"
8
+ gem.summary = %Q{buzzcorej is the JRuby core library developed and used by Buzzware Solutions.}
9
+ gem.description = %Q{buzzcorej is the JRuby core library developed and used by Buzzware Solutions.}
10
+ gem.email = "contact@buzzware.com.au"
11
+ gem.homepage = "http://github.com/buzzware/buzzcorej"
12
+ gem.authors = ["buzzware"]
13
+ gem.add_development_dependency "shoulda"
14
+ gem.files.include %w(
15
+ lib/buzzcorej.rb
16
+ )
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ end
19
+ Jeweler::GemcutterTasks.new
20
+ Jeweler::RubyforgeTasks.new do |rubyforge|
21
+ rubyforge.doc_task = "rdoc"
22
+ end
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
25
+ end
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/*_test.rb'
39
+ test.verbose = true
40
+ end
41
+ rescue LoadError
42
+ task :rcov do
43
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44
+ end
45
+ end
46
+
47
+ task :test => :check_dependencies
48
+
49
+ task :default => :test
50
+
51
+ require 'rake/rdoctask'
52
+ Rake::RDocTask.new do |rdoc|
53
+ if File.exist?('VERSION')
54
+ version = File.read('VERSION')
55
+ else
56
+ version = ""
57
+ end
58
+
59
+ rdoc.rdoc_dir = 'rdoc'
60
+ rdoc.title = "buzzcorej #{version}"
61
+ rdoc.rdoc_files.include('README*')
62
+ rdoc.rdoc_files.include('lib/**/*.rb')
63
+ end
data/VERSION ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.2
2
+
@@ -0,0 +1,58 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{buzzcorej}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["buzzware"]
12
+ s.date = %q{2010-08-15}
13
+ s.description = %q{buzzcorej is the JRuby core library developed and used by Buzzware Solutions.}
14
+ s.email = %q{contact@buzzware.com.au}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "buzzcorej.gemspec",
25
+ "buzzcorej.vpj",
26
+ "buzzcorej.vpw",
27
+ "lib/buzzcorej.rb",
28
+ "lib/buzzcorej/enum.rb",
29
+ "lib/buzzcorej/extend_base_classes.rb",
30
+ "lib/buzzcorej/misc_utils.rb",
31
+ "lib/buzzcorej/require_paths.rb",
32
+ "lib/buzzcorej/string_utils.rb",
33
+ "lib/buzzcorej_dev.rb",
34
+ "test/test_helper.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/buzzware/buzzcorej}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.7}
40
+ s.summary = %q{buzzcorej is the JRuby core library developed and used by Buzzware Solutions.}
41
+ s.test_files = [
42
+ "test/test_helper.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
51
+ else
52
+ s.add_dependency(%q<shoulda>, [">= 0"])
53
+ end
54
+ else
55
+ s.add_dependency(%q<shoulda>, [">= 0"])
56
+ end
57
+ end
58
+
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
2
+ <Project
3
+ Version="10.0"
4
+ VendorName="SlickEdit"
5
+ WorkingDir=".">
6
+ <Config
7
+ Name="Release"
8
+ OutputFile=""
9
+ CompilerConfigName="Latest Version">
10
+ <Menu>
11
+ <Target
12
+ Name="Compile"
13
+ MenuCaption="&amp;Compile"
14
+ CaptureOutputWith="ProcessBuffer"
15
+ SaveOption="SaveCurrent"
16
+ RunFromDir="%rw">
17
+ <Exec/>
18
+ </Target>
19
+ <Target
20
+ Name="Build"
21
+ MenuCaption="&amp;Build"
22
+ CaptureOutputWith="ProcessBuffer"
23
+ SaveOption="SaveWorkspaceFiles"
24
+ RunFromDir="%rw">
25
+ <Exec/>
26
+ </Target>
27
+ <Target
28
+ Name="Rebuild"
29
+ MenuCaption="&amp;Rebuild"
30
+ CaptureOutputWith="ProcessBuffer"
31
+ SaveOption="SaveWorkspaceFiles"
32
+ RunFromDir="%rw">
33
+ <Exec/>
34
+ </Target>
35
+ <Target
36
+ Name="Debug"
37
+ MenuCaption="&amp;Debug"
38
+ SaveOption="SaveNone"
39
+ RunFromDir="%rw">
40
+ <Exec/>
41
+ </Target>
42
+ <Target
43
+ Name="Execute"
44
+ MenuCaption="E&amp;xecute"
45
+ SaveOption="SaveNone"
46
+ RunFromDir="%rw"
47
+ CaptureOutputWith="ProcessBuffer"
48
+ ClearProcessBuffer="1">
49
+ <Exec CmdLine="source actions.sh execute"/>
50
+ </Target>
51
+ </Menu>
52
+ </Config>
53
+ <CustomFolders>
54
+ <Folder
55
+ Name="Source Files"
56
+ Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl"/>
57
+ <Folder
58
+ Name="Header Files"
59
+ Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if"/>
60
+ <Folder
61
+ Name="Resource Files"
62
+ Filters="*.ico;*.cur;*.dlg"/>
63
+ <Folder
64
+ Name="Bitmaps"
65
+ Filters="*.bmp"/>
66
+ <Folder
67
+ Name="Other Files"
68
+ Filters="">
69
+ </Folder>
70
+ </CustomFolders>
71
+ <Files AutoFolders="DirectoryView">
72
+ <Folder Name="lib">
73
+ <F
74
+ N="lib/*"
75
+ Recurse="1"
76
+ Refilter="0"
77
+ Excludes=""/>
78
+ </Folder>
79
+ <Folder Name="test">
80
+ <F
81
+ N="test/*"
82
+ Recurse="0"
83
+ Refilter="0"
84
+ Excludes=".svn/"/>
85
+ </Folder>
86
+ <F N="buzzcorej.gemspec"/>
87
+ <F N="History.txt"/>
88
+ <F N="Manifest.txt"/>
89
+ <F N="PostInstall.txt"/>
90
+ <F N="Rakefile"/>
91
+ <F N="README.rdoc"/>
92
+ </Files>
93
+ </Project>
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
2
+ <Project
3
+ Version="10.0"
4
+ VendorName="SlickEdit"
5
+ WorkingDir=".">
6
+ <Config
7
+ Name="Release"
8
+ OutputFile=""
9
+ CompilerConfigName="Latest Version">
10
+ <Menu>
11
+ <Target
12
+ Name="Compile"
13
+ MenuCaption="&amp;Compile"
14
+ CaptureOutputWith="ProcessBuffer"
15
+ SaveOption="SaveCurrent"
16
+ RunFromDir="%rw">
17
+ <Exec/>
18
+ </Target>
19
+ <Target
20
+ Name="Build"
21
+ MenuCaption="&amp;Build"
22
+ CaptureOutputWith="ProcessBuffer"
23
+ SaveOption="SaveWorkspaceFiles"
24
+ RunFromDir="%rw">
25
+ <Exec/>
26
+ </Target>
27
+ <Target
28
+ Name="Rebuild"
29
+ MenuCaption="&amp;Rebuild"
30
+ CaptureOutputWith="ProcessBuffer"
31
+ SaveOption="SaveWorkspaceFiles"
32
+ RunFromDir="%rw">
33
+ <Exec/>
34
+ </Target>
35
+ <Target
36
+ Name="Debug"
37
+ MenuCaption="&amp;Debug"
38
+ SaveOption="SaveNone"
39
+ RunFromDir="%rw">
40
+ <Exec/>
41
+ </Target>
42
+ <Target
43
+ Name="Execute"
44
+ MenuCaption="E&amp;xecute"
45
+ SaveOption="SaveNone"
46
+ RunFromDir="%rw"
47
+ CaptureOutputWith="ProcessBuffer"
48
+ ClearProcessBuffer="1">
49
+ <Exec CmdLine="source actions.sh execute"/>
50
+ </Target>
51
+ </Menu>
52
+ </Config>
53
+ <CustomFolders>
54
+ <Folder
55
+ Name="Source Files"
56
+ Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl"/>
57
+ <Folder
58
+ Name="Header Files"
59
+ Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if"/>
60
+ <Folder
61
+ Name="Resource Files"
62
+ Filters="*.ico;*.cur;*.dlg"/>
63
+ <Folder
64
+ Name="Bitmaps"
65
+ Filters="*.bmp"/>
66
+ <Folder
67
+ Name="Other Files"
68
+ Filters="">
69
+ </Folder>
70
+ </CustomFolders>
71
+ <Files AutoFolders="DirectoryView">
72
+ <Folder Name="lib">
73
+ <F
74
+ N="lib/*"
75
+ Recurse="1"
76
+ Refilter="0"
77
+ Excludes=""/>
78
+ </Folder>
79
+ <Folder Name="test">
80
+ <F
81
+ N="test/*"
82
+ Recurse="0"
83
+ Refilter="0"
84
+ Excludes=".svn/"/>
85
+ </Folder>
86
+ <F N="buzzcorej.gemspec"/>
87
+ <F N="History.txt"/>
88
+ <F N="Manifest.txt"/>
89
+ <F N="PostInstall.txt"/>
90
+ <F N="Rakefile"/>
91
+ <F N="README.rdoc"/>
92
+ </Files>
93
+ </Project>
@@ -0,0 +1,50 @@
1
+ module Kernel
2
+ # simple (sequential) enumerated values
3
+ # usage :
4
+ #
5
+ # module Constants
6
+ # module Gradient
7
+ # enum :B, :A, :C
8
+ # end
9
+ # end
10
+ #
11
+ # then :
12
+ #
13
+ # puts Constants::Gradient::B -> 0
14
+ # puts Constants::Gradient::C -> 2
15
+ # puts Constants::Gradient::MINVALUE -> 0
16
+ # puts Constants::Gradient::MAXVALUE -> 2
17
+ # puts Constants::Gradient::NAMES -> [:B, :A, :C]
18
+ # puts Constants::Gradient[0] -> :B
19
+ # puts Constants::Gradient[1] -> :A
20
+ # puts Constants::Gradient[2] -> :C
21
+
22
+ def enum(*syms)
23
+ syms.each_index { |i|
24
+ const_set(syms[i], i)
25
+ }
26
+ const_set(:NAMES, syms || [])
27
+ const_set(:MINVALUE, syms==nil ? nil : 0)
28
+ const_set(:MAXVALUE, syms==nil ? nil : syms.length-1)
29
+ const_set(:VALUECOUNT, syms==nil ? nil : syms.length)
30
+ const_set(:ALL, syms==nil ? [] : (0..syms.length-1).to_a)
31
+ const_set(:HUMAN_NAMES, syms.map{|n| n.to_s.humanize} || [])
32
+
33
+ # this returns the enum name given the value
34
+ def self.[]( idx )
35
+ (idx.is_a? Integer) ? const_get(:NAMES)[idx] : nil
36
+ end
37
+
38
+ def self.valid?(idx)
39
+ (idx.is_a? Integer) && (idx >= 0) && (idx <= const_get(:MAXVALUE))
40
+ end
41
+
42
+ def self.parse(name,default=nil)
43
+ return default if name.nil? || name.empty?
44
+ return default if not name = name.to_sym
45
+ result = const_get(:NAMES).index(name)
46
+ return result==nil ? default : result
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,485 @@
1
+ String.class_eval do
2
+ def pad_left(value)
3
+ increase = value-self.length
4
+ return self if increase==0
5
+ if increase > 0
6
+ return self + ' '*increase
7
+ else
8
+ return self[0,value]
9
+ end
10
+ end
11
+
12
+ def pad_right(value)
13
+ increase = value-self.length
14
+ return self if increase==0
15
+ if increase > 0
16
+ return ' '*increase + self
17
+ else
18
+ return self[0,value]
19
+ end
20
+ end
21
+
22
+ # Like chomp! but operates on the leading characters instead.
23
+ # The aString parameter would not normally be used.
24
+ def bite!(aValue=$/,aString=self)
25
+ if aString[0,aValue.length] == aValue
26
+ aString[0,aValue.length] = ''
27
+ return aString
28
+ else
29
+ return aString
30
+ end
31
+ end
32
+
33
+ def bite(aValue=$/)
34
+ bite!(aValue,self.clone)
35
+ end
36
+
37
+ def begins_with?(aString)
38
+ self[0,aString.length]==aString
39
+ end
40
+
41
+ def ends_with?(aString)
42
+ self[-aString.length,aString.length]==aString
43
+ end
44
+
45
+ # for future methods
46
+ # def centre_bar(aChar = '-', indent = 6)
47
+ # (' '*indent) + aChar*(@width-(indent*2)) + (' '*indent)
48
+ # end
49
+ # def replace_string(aString,aCol,aSubString)
50
+ # return aString if aSubString==nil || aSubString==''
51
+ #
52
+ # aSubString = aSubString.to_s
53
+ # start_col = aCol < 0 ? 0 : aCol
54
+ # end_col = aCol+aSubString.length-1
55
+ # end_col = @width-1 if end_col >= @width
56
+ # source_len = end_col-start_col+1
57
+ # return aString if source_len <= 0 || end_col < 0 || start_col >= @width
58
+ # aString += ' '*((end_col+1) - aString.length) if aString.length < end_col+1
59
+ # aString[start_col,source_len] = aSubString[start_col-aCol,end_col-start_col+1]
60
+ # return aString
61
+ # end
62
+
63
+ def to_integer(aDefault=nil)
64
+ t = self.strip
65
+ return aDefault if t.empty? || !t.index(/^-{0,1}[0-9]+$/)
66
+ return t.to_i
67
+ end
68
+
69
+ def is_i?
70
+ self.to_integer(false) and true
71
+ end
72
+
73
+ def to_float(aDefault=nil)
74
+ t = self.strip
75
+ return aDefault if !t =~ /(\+|-)?([0-9]+\.?[0-9]*|\.[0-9]+)([eE](\+|-)?[0-9]+)?/
76
+ return t.to_f
77
+ end
78
+
79
+ def is_f?
80
+ self.to_float(false) and true
81
+ end
82
+
83
+ # like scan but returns array of MatchData's.
84
+ # doesn't yet support blocks
85
+ def scan_md(aPattern)
86
+ result = []
87
+ self.scan(aPattern) {|s| result << $~ }
88
+ result
89
+ end
90
+
91
+ def to_nil(aPattern=nil)
92
+ return nil if self.empty?
93
+ if aPattern
94
+ return nil if (aPattern.is_a? Regexp) && (self =~ aPattern)
95
+ return nil if aPattern.to_s == self
96
+ end
97
+ self
98
+ end
99
+
100
+ def to_b(aDefault=false)
101
+ return true if ['1','yes','y','true','on'].include?(self.downcase)
102
+ return false if ['0','no','n','false','off'].include?(self.downcase)
103
+ aDefault
104
+ end
105
+
106
+ # uses
107
+ #URLIZE_PATTERN = /[ \/\\\(\)\[\]]/
108
+ URLIZE_PATTERN_PS = /[ \\\(\)\[\]_]/
109
+ def urlize(aSlashChar='+')
110
+ return self if self.empty?
111
+ result = self.gsub(URLIZE_PATTERN_PS,'-').downcase.gsub(/[^a-z0-9_\-+,\.\/]/,'')
112
+ result.gsub!('/',aSlashChar) unless aSlashChar=='/'
113
+ result.gsub!(/-{2,}/,'-')
114
+ result
115
+ end
116
+
117
+ private
118
+ CRC_LOOKUP = [
119
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
120
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
121
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
122
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
123
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
124
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
125
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
126
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
127
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
128
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
129
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
130
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
131
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
132
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
133
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
134
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
135
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
136
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
137
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
138
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
139
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
140
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
141
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
142
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
143
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
144
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
145
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
146
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
147
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
148
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
149
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
150
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
151
+ ]
152
+ public
153
+
154
+ def crc16
155
+ crc = 0x00
156
+ self.each_byte do |b|
157
+ crc = ((crc >> 8) & 0xff) ^ CRC_LOOKUP[(crc ^ b) & 0xff]
158
+ end
159
+ crc
160
+ end
161
+
162
+
163
+ end
164
+
165
+
166
+ Time.class_eval do
167
+
168
+ if !respond_to?(:change) # no activesupport loaded
169
+ def change(options)
170
+ ::Time.send(
171
+ self.utc? ? :utc : :local,
172
+ options[:year] || self.year,
173
+ options[:month] || self.month,
174
+ options[:day] || self.day,
175
+ options[:hour] || self.hour,
176
+ options[:min] || (options[:hour] ? 0 : self.min),
177
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
178
+ options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
179
+ )
180
+ end
181
+
182
+ def seconds_since_midnight
183
+ self.to_i - self.change(:hour => 0).to_i + (self.usec/1.0e+6)
184
+ end
185
+
186
+ def beginning_of_day
187
+ (self - self.seconds_since_midnight).change(:usec => 0)
188
+ end
189
+
190
+ alias :midnight :beginning_of_day
191
+ alias :at_midnight :beginning_of_day
192
+ alias :at_beginning_of_day :beginning_of_day
193
+
194
+ end
195
+
196
+ # offset of local machine from UTC, in seconds eg +9.hours
197
+ def self.local_offset
198
+ local(2000).utc_offset
199
+ end
200
+
201
+ def date
202
+ self.at_beginning_of_day
203
+ end
204
+
205
+ # index number of this day, from Time.at(0) + utc_offset
206
+ def day_number
207
+ (self.to_i+self.utc_offset) / 86400
208
+ end
209
+
210
+ # index number of this utc day
211
+ def day_number_utc
212
+ self.to_i / 86400
213
+ end
214
+
215
+ # the last microsecond of the day
216
+ def day_end
217
+ self.at_beginning_of_day + 86399.999999
218
+ end
219
+
220
+ def date_numeric
221
+ self.strftime('%Y%m%d')
222
+ end
223
+
224
+ def to_universal
225
+ self.strftime("%d %b %Y")
226
+ end
227
+
228
+ # create a new Time from eg. "20081231"
229
+ def self.from_date_numeric(aString)
230
+ return nil unless aString
231
+ local(aString[0,4].to_i,aString[4,2].to_i,aString[6,2].to_i)
232
+ end
233
+
234
+ def time_numeric
235
+ self.strftime('%H%M%S')
236
+ end
237
+
238
+ def datetime_numeric
239
+ self.strftime('%Y%m%d-%H%M%S')
240
+ end
241
+
242
+ def to_sql
243
+ self.strftime('%Y-%m-%d %H:%M:%S')
244
+ end
245
+
246
+ def to_w3c
247
+ utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")
248
+ end
249
+ end
250
+
251
+ module HashUtils
252
+ def filter_include!(aKeys,aHash=nil)
253
+ aHash ||= self
254
+
255
+ if aKeys.is_a? Regexp
256
+ return aHash.delete_if {|k,v| not k =~ aKeys }
257
+ else
258
+ aKeys = [aKeys] unless aKeys.is_a? Array
259
+ return aHash.clear if aKeys.empty?
260
+ return aHash.delete_if {|key, value| !((aKeys.include?(key)) || (key.is_a?(Symbol) and aKeys.include?(key.to_s)) || (key.is_a?(String) and aKeys.include?(key.to_sym)))}
261
+ return aHash # last resort
262
+ end
263
+ end
264
+
265
+ def filter_include(aKeys,aHash=nil)
266
+ aHash ||= self
267
+ filter_include!(aKeys,aHash.clone)
268
+ end
269
+
270
+ def filter_exclude!(aKeys,aHash=nil)
271
+ aHash ||= self
272
+
273
+ if aKeys.is_a? Regexp
274
+ return aHash.delete_if {|k,v| k =~ aKeys }
275
+ else
276
+ aKeys = [aKeys] unless aKeys.is_a? Array
277
+ return aHash if aKeys.empty?
278
+ return aHash.delete_if {|key, value| ((aKeys.include?(key)) || (key.is_a?(Symbol) and aKeys.include?(key.to_s)) || (key.is_a?(String) and aKeys.include?(key.to_sym)))}
279
+ end
280
+ end
281
+
282
+ def filter_exclude(aKeys,aHash=nil)
283
+ aHash ||= self
284
+ filter_exclude!(aKeys,aHash.clone)
285
+ end
286
+
287
+ def has_values_for?(aKeys,aHash=nil)
288
+ aHash ||= self
289
+ # check all keys exist in aHash and their values are not nil
290
+ aKeys.all? { |k,v| aHash[k] }
291
+ end
292
+
293
+ # give a block to execute without the given key in this hash
294
+ # It will be replaced after the block (guaranteed by ensure)
295
+ # eg.
296
+ # hash.without_key(:blah) do |aHash|
297
+ # puts aHash.inspect
298
+ # end
299
+ def without_key(aKey)
300
+ temp = nil
301
+ h = self
302
+ begin
303
+ if h.include?(aKey)
304
+ temp = [aKey,h.delete(aKey)]
305
+ end
306
+ result = yield(h)
307
+ ensure
308
+ h[temp[0]] = temp[1] if temp
309
+ end
310
+ return result
311
+ end
312
+
313
+ def symbolize_keys
314
+ result = {}
315
+ self.each { |k,v| k.is_a?(String) ? result[k.to_sym] = v : result[k] = v }
316
+ return result
317
+ end
318
+
319
+ def to_nil
320
+ self.empty? ? nil : self
321
+ end
322
+
323
+ end
324
+
325
+ Hash.class_eval do
326
+ include HashUtils
327
+ end
328
+
329
+ if defined? HashWithIndifferentAccess
330
+ HashWithIndifferentAccess.class_eval do
331
+ include HashUtils
332
+ end
333
+ end
334
+
335
+ module ArrayUtils
336
+ def filter_include!(aValues,aArray=nil)
337
+ aArray ||= self
338
+ if aValues.is_a? Array
339
+ return aArray if aValues.empty?
340
+ return aArray.delete_if {|v| not aValues.include? v }
341
+ elsif aValues.is_a? Regexp
342
+ return aArray.delete_if {|v| not v =~ aValues }
343
+ else
344
+ return filter_include!([aValues],aArray)
345
+ end
346
+ end
347
+
348
+ def filter_include(aValues,aArray=nil)
349
+ aArray ||= self
350
+ filter_include!(aValues,aArray.clone)
351
+ end
352
+
353
+ def filter_exclude!(aValues,aArray=nil)
354
+ aArray ||= self
355
+ if aValues.is_a? Array
356
+ return aArray if aValues.empty?
357
+ return aArray.delete_if {|v| aValues.include? v }
358
+ elsif aValues.is_a? Regexp
359
+ return aArray.delete_if {|v| v =~ aValues }
360
+ else
361
+ return filter_exclude!([aValues],aArray)
362
+ end
363
+ end
364
+
365
+ def filter_exclude(aValues,aArray=nil)
366
+ aArray ||= self
367
+ filter_exclude!(aValues,aArray.clone)
368
+ end
369
+
370
+ def to_nil
371
+ self.empty? ? nil : self
372
+ end
373
+
374
+ end
375
+
376
+ Array.class_eval do
377
+ include ArrayUtils
378
+
379
+ # fixes a memory leak in shift in Ruby 1.8 - should be fixed in 1.9
380
+ # see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/216055
381
+ def shift()
382
+ delete_at(0)
383
+ end
384
+
385
+ end
386
+
387
+ Kernel.class_eval do
388
+ def is_windows?
389
+ RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
390
+ end
391
+ end
392
+
393
+ if defined? ActiveRecord
394
+ ActiveRecord::Base.class_eval do
395
+
396
+ def self.find_any_id(aId)
397
+ with_exclusive_scope { find(:first, {:conditions => {:id => aId}}) }
398
+ end
399
+
400
+ def self.find_any_all(aOptions={})
401
+ with_exclusive_scope { find(:all, aOptions) }
402
+ end
403
+
404
+ def self.find_ids(aIds)
405
+ find(:all, {:conditions=> ["id in (?)",aIds.join(',')]})
406
+ end
407
+
408
+ def self.find_any_ids(aIds)
409
+ with_exclusive_scope { find(:all, {:conditions=> ["id in (?)",aIds.join(',')]}) }
410
+ end
411
+
412
+ end
413
+ end
414
+
415
+ Fixnum.class_eval do
416
+
417
+ def to_nil
418
+ self==0 ? nil : self
419
+ end
420
+
421
+ def to_b(aDefault=false)
422
+ self==0 ? false : true
423
+ end
424
+
425
+ end
426
+
427
+ Bignum.class_eval do
428
+
429
+ def to_nil
430
+ self==0 ? nil : self
431
+ end
432
+
433
+ def to_b(aDefault=false)
434
+ self==0 ? false : true
435
+ end
436
+
437
+ end
438
+
439
+ NilClass.class_eval do
440
+
441
+ def to_nil
442
+ nil
443
+ end
444
+
445
+ def to_b(aDefault=false)
446
+ false
447
+ end
448
+
449
+ end
450
+
451
+ TrueClass.class_eval do
452
+
453
+ def to_nil
454
+ self
455
+ end
456
+
457
+ def to_b(aDefault=false)
458
+ self
459
+ end
460
+
461
+ end
462
+
463
+ FalseClass.class_eval do
464
+
465
+ def to_nil
466
+ nil
467
+ end
468
+
469
+ def to_b(aDefault=false)
470
+ self
471
+ end
472
+
473
+ end
474
+
475
+
476
+ Math.module_eval do
477
+ def self.max(a, b)
478
+ a > b ? a : b
479
+ end
480
+
481
+ def self.min(a, b)
482
+ a < b ? a : b
483
+ end
484
+ end
485
+
@@ -0,0 +1,334 @@
1
+ require 'tmpdir'
2
+ require 'logger'
3
+ require 'pathname'
4
+
5
+ #require 'buzzcorej/logging'
6
+
7
+ module MiscUtils
8
+
9
+ def self.logger
10
+ @logger || @logger = Logger.new(STDERR)
11
+ end
12
+
13
+ # applies the given block to key/value pairs included/excluded by the given parameters
14
+ # aSource must be a hash, and may contain hashes which will be recursively processed.
15
+ # aInclude/aExclude may be nil, an array of selected keys, or a hash containing arrays of keys for inner hashes of aSource
16
+ # When aInclude/aExclude are a hash, non-hash source values may be selected by passing a value of true. Hash source values
17
+ # will be selected as a whole (all keys) when true is passed.
18
+ # input = { 'a' => 1, 'b' => {'x' => 9, 'y' => 8}, 'c' => 3 }
19
+ # filter_multilevel_hash(input,['a','b'],{'b'=>['y']}) {|h,k,v| h[k] = true}
20
+ # input now = { 'a' => true, 'b' => {'x' => true, 'y' => 8}, 'c' => 3 }
21
+ def self.filter_multilevel_hash(aSource,aInclude=nil,aExclude=nil,&block)
22
+ aSource.each do |key,value|
23
+ next if aInclude.is_a?(Array) and !aInclude.include?(key) # skip if not in aInclude array
24
+ next if aExclude.is_a?(Array) and aExclude.include?(key) # skip if in aExclude array
25
+ next if aExclude.is_a?(Hash) and aExclude[key]==true # skip if in aExclude hash with value=true
26
+ next if aInclude.is_a?(Hash) and !aInclude.include?(key) # skip if not in aInclude hash at all
27
+ if value.is_a?(Hash) # value is hash so recursively apply filter
28
+ filter_multilevel_hash(
29
+ value,
30
+ aInclude.is_a?(Hash) && (f = aInclude[key]) ? f : nil, # pass include array if provided for key
31
+ aExclude.is_a?(Hash) && (f = aExclude[key]) ? f : nil, # pass exclude array if provided for key
32
+ &block
33
+ )
34
+ else
35
+ yield(aSource,key,value)
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.temp_file(aExt=nil,aDir=nil)
41
+ aExt ||= '.tmp'
42
+ File.expand_path(("%08X" % rand(0x3FFFFFFF)) + aExt, aDir||Dir.tmpdir)
43
+ end
44
+
45
+ def self.make_temp_file(aName=nil,aDir=nil,aContent=nil)
46
+ filename = aName ? File.expand_path(aName,aDir || Dir.tmpdir) : temp_file(nil,aDir)
47
+ FileUtils.mkdir_p(File.dirname(filename))
48
+ aContent ||= "content of "+filename
49
+ string_to_file(aContent,filename)
50
+ filename
51
+ end
52
+
53
+ def self.make_temp_dir(aPrefix='')
54
+ new_dir = nil
55
+ begin
56
+ new_dir = File.join(Dir.tmpdir,aPrefix+("%08X" % rand(0x3FFFFFFF)))
57
+ end until new_dir && !File.exists?(new_dir)
58
+ Dir.mkdir new_dir
59
+ return new_dir
60
+ end
61
+
62
+ def self.mkdir?(aPath,aPermissions)
63
+ if File.exists?(aPath)
64
+ File.chmod(aPermissions, aPath)
65
+ else
66
+ Dir.mkdir(aPath, aPermissions)
67
+ end
68
+ end
69
+
70
+ #def self.set_permissions_cmd(aFilepath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false,aSudo=true)
71
+ # cmd = []
72
+ # if aGroup
73
+ # cmd << (aUser ? "#{aSudo ? sudo : ''} chown #{aUser}:#{aGroup}" : "#{aSudo ? sudo : ''} chgrp #{aGroup}") + " #{aFilepath}"
74
+ # else
75
+ # cmd << "#{aSudo ? sudo : ''} chown #{aUser} #{aFilepath}" if aUser
76
+ # end
77
+ # cmd << "#{aSudo ? sudo : ''} chmod #{aMode.to_s} #{aFilepath}" if aMode
78
+ # cmd << "#{aSudo ? sudo : ''} chmod g+s #{aFilepath}" if aSetGroupId
79
+ # cmd.join(' && ')
80
+ #end
81
+
82
+ def self.string_to_file(aString,aFilename)
83
+ File.open(aFilename,'wb') {|file| file.write aString }
84
+ end
85
+
86
+ def self.string_from_file(aFilename)
87
+ result = nil
88
+ File.open(aFilename, "rb") { |f| result = f.read }
89
+ # return result && result[0..-2] # quick hack to stop returning false \n at end UPDATE: this is causing problems now
90
+ end
91
+
92
+ def self.sniff_seperator(aPath)
93
+ result = 0.upto(aPath.length-1) do |i|
94
+ char = aPath[i,1]
95
+ break char if char=='\\' || char=='/'
96
+ end
97
+ result = File::SEPARATOR if result==0
98
+ return result
99
+ end
100
+
101
+ def self.append_slash(aPath,aSep=nil)
102
+ aSep = sniff_seperator(aPath) unless aSep
103
+ last_char = aPath[-1,1]
104
+ aPath += aSep unless last_char=='\\' || last_char=='/'
105
+ return aPath
106
+ end
107
+
108
+ def self.remove_slash(aPath)
109
+ last_char = aPath[-1,1]
110
+ aPath = aPath[0..-2] if last_char=='\\' || last_char=='/'
111
+ return aPath
112
+ end
113
+
114
+ # Remove base dir from given path. Result will be relative to base dir and not have a leading or trailing slash
115
+ #'/a/b/c','/a' = 'b/c'
116
+ #'/a/b/c','/' = 'a/b/c'
117
+ #'/','/' = ''
118
+ def self.path_debase(aPath,aBase)
119
+ aBase = MiscUtils::append_slash(aBase)
120
+ aPath = MiscUtils::remove_slash(aPath) unless aPath=='/'
121
+ aPath[0,aBase.length]==aBase ? aPath[aBase.length,aPath.length-aBase.length] : aPath
122
+ end
123
+
124
+ def self.path_rebase(aPath,aOldBase,aNewBase)
125
+ rel_path = path_debase(aPath,aOldBase)
126
+ append_slash(aNewBase)+rel_path
127
+ end
128
+
129
+ def self.path_combine(aBasePath,aPath)
130
+ return aBasePath if !aPath
131
+ return aPath if !aBasePath
132
+ return path_relative?(aPath) ? File.join(aBasePath,aPath) : aPath
133
+ end
134
+
135
+ # make path real according to file system
136
+ def self.real_path(aPath)
137
+ (path = Pathname.new(File.expand_path(aPath))) && path.realpath.to_s
138
+ end
139
+
140
+ # takes a path and combines it with a root path (which defaults to Dir.pwd) unless it is absolute
141
+ # the final result is then expanded
142
+ def self.canonize_path(aPath,aRootPath=nil)
143
+ path = path_combine(aRootPath,aPath)
144
+ path = real_path(path) if path
145
+ path
146
+ end
147
+
148
+ def self.find_upwards(aStartPath,aPath)
149
+ curr_path = File.expand_path(aStartPath)
150
+ while curr_path && !(test_path_exists = File.exists?(test_path = File.join(curr_path,aPath))) do
151
+ curr_path = MiscUtils.path_parent(curr_path)
152
+ end
153
+ curr_path && test_path_exists ? test_path : nil
154
+ end
155
+
156
+
157
+ # allows special symbols in path
158
+ # currently only ... supported, which looks upward in the filesystem for the following relative path from the basepath
159
+ def self.expand_magic_path(aPath,aBasePath=nil)
160
+ aBasePath ||= Dir.pwd
161
+ path = aPath
162
+ if path.begins_with?('...')
163
+ rel_part = StringUtils.split3(path,/\.\.\.[\/\\]/)[2]
164
+ path = find_upwards(aBasePath,rel_part)
165
+ end
166
+ end
167
+
168
+ def self.path_parent(aPath)
169
+ return nil if is_root_path?(aPath)
170
+ MiscUtils.append_slash(File.dirname(MiscUtils.remove_slash(File.expand_path(aPath))))
171
+ end
172
+
173
+ def self.simple_dir_name(aPath)
174
+ File.basename(remove_slash(aPath))
175
+ end
176
+
177
+ def self.simple_file_name(aPath)
178
+ f = File.basename(aPath)
179
+ dot = f.index('.')
180
+ return dot ? f[0,dot] : f
181
+ end
182
+
183
+ def self.path_parts(aPath)
184
+ sep = sniff_seperator(aPath)
185
+ aPath.split(sep)
186
+ end
187
+
188
+ def self.file_extension(aFile,aExtended=true)
189
+ f = File.basename(aFile)
190
+ dot = aExtended ? f.index('.') : f.rindex('.')
191
+ return dot ? f[dot+1..-1] : f
192
+ end
193
+
194
+ def self.file_no_extension(aFile,aExtended=true)
195
+ ext = file_extension(aFile,aExtended)
196
+ return aFile.chomp('.'+ext)
197
+ end
198
+
199
+ def self.file_change_ext(aFile,aExt,aExtend=false)
200
+ file_no_extension(aFile,false)+(aExtend ? '.'+aExt+'.'+file_extension(aFile,false) : '.'+aExt)
201
+ end
202
+
203
+ def self.platform
204
+ RUBY_PLATFORM.scan(/-(.+)$/).flatten.first
205
+ end
206
+
207
+ def self.windows_path(aPath)
208
+ aPath.gsub('/','\\')
209
+ end
210
+
211
+ def self.ruby_path(aPath)
212
+ aPath.gsub('\\','/')
213
+ end
214
+
215
+ def self.is_uri?(aString)
216
+ /^[a-zA-Z0-9+_]+\:\/\// =~ aString ? true : false
217
+ end
218
+
219
+ def self.is_root_path?(aPath)
220
+ if is_windows?
221
+ (aPath =~ /^[a-zA-Z]\:[\\\/]$/)==0
222
+ else
223
+ aPath == '/'
224
+ end
225
+ end
226
+
227
+ def self.native_path(aPath)
228
+ is_windows? ? windows_path(aPath) : ruby_path(aPath)
229
+ end
230
+
231
+ def self.path_relative?(aPath)
232
+ return false if aPath[0,1]=='/'
233
+ return false if aPath =~ /^[a-zA-Z]:/
234
+ return true
235
+ end
236
+
237
+ def self.path_absolute?(aPath)
238
+ !path_relative(aPath)
239
+ end
240
+
241
+ def self.is_windows?
242
+ platform=='mswin32'
243
+ end
244
+
245
+ def self.get_files(aArray,aPath,aFullPath=true,aRootPath=nil,&block)
246
+ #puts "get_files: aPath='#{aPath}'"
247
+ if aRootPath
248
+ abssrcpath = path_combine(aRootPath,aPath)
249
+ else
250
+ abssrcpath = aRootPath = aPath
251
+ aPath = nil
252
+ end
253
+ return aArray if !File.exists?(abssrcpath)
254
+ #abssrcpath is real path to query
255
+ #aRootPath is highest level path
256
+ #aPath is current path relative to aRootPath
257
+ Dir.new(abssrcpath).to_a.each do |file|
258
+ next if ['.','..'].include? file
259
+ fullpath = File.join(abssrcpath,file)
260
+ resultpath = aFullPath ? fullpath : path_combine(aPath,file)
261
+ if !block_given? || yield(resultpath)
262
+ if FileTest.directory?(fullpath)
263
+ block_given? ? get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath,&block) : get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath)
264
+ else
265
+ aArray << resultpath
266
+ end
267
+ end
268
+ end
269
+ return aArray
270
+ end
271
+
272
+ def self.recursive_file_list(aPath,aFullPath=true,&block)
273
+ block_given? ? get_files([],aPath,aFullPath,nil,&block) : get_files([],aPath,aFullPath)
274
+ end
275
+
276
+ # returns true if aPath1 and aPath2 are the same path (doesn't query file system)
277
+ # both must be absolute or both relative
278
+ def self.path_same(aPath1,aPath2)
279
+ return nil unless path_relative?(aPath1) == path_relative?(aPath2)
280
+ remove_slash(aPath1) == remove_slash(aPath2)
281
+ end
282
+
283
+ # returns true if aPath is under aPathParent
284
+ # both must be absolute or both relative
285
+ def self.path_ancestor(aPathParent,aPath)
286
+ return nil unless path_relative?(aPathParent) == path_relative?(aPath)
287
+ aPath.index(append_slash(aPathParent))==0
288
+ end
289
+
290
+ # returns the lowest path containing all files (assumes aFiles contains only absolute paths)
291
+ def self.file_list_ancestor(aFiles)
292
+ files = aFiles.is_a?(Hash) ? aFiles.keys : aFiles
293
+ result = File.dirname(files.first)
294
+ files.each do |fp|
295
+ filedir = File.dirname(fp)
296
+ while path_same(result,filedir)==false && path_ancestor(result,filedir)==false
297
+ result = path_parent(result)
298
+ end
299
+ end
300
+ result
301
+ end
302
+
303
+ def self.path_match(aPath,aPatterns)
304
+ aPatterns = [aPatterns] unless aPatterns.is_a? Array
305
+ aPatterns.any? do |pat|
306
+ case pat
307
+ when String then aPath[0,pat.length] == pat
308
+ when Regexp then aPath =~ pat
309
+ else false
310
+ end
311
+ end
312
+ end
313
+
314
+ # takes a hash and returns a single closed tag containing the hash pairs as attributes, correctly encoded
315
+ def self.hash_to_xml_tag(aName,aHash)
316
+ atts = ''
317
+ aHash.each do |k,v|
318
+ atts += ' ' + k.to_s + "=\"#{v.to_s.to_xs}\""
319
+ end
320
+ "<#{aName}#{atts}/>"
321
+ end
322
+
323
+ def self.filelist_from_patterns(aPatterns,aBasePath)
324
+ return [] unless aPatterns
325
+ aPatterns = [aPatterns] unless aPatterns.is_a? Array
326
+
327
+ aPatterns.map do |fp|
328
+ fp = File.expand_path(fp,aBasePath) # relative to rails root
329
+ fp = FileList[fp] if fp['*'] || fp['?']
330
+ fp
331
+ end.flatten
332
+ end
333
+ end
334
+
@@ -0,0 +1,39 @@
1
+ # This sorts out the issues of require'ing files in Ruby
2
+ # 1) on one line, you specify all the paths you need
3
+ # 2) Relative paths will be relative to the file you are in, absolute paths also supported
4
+ # 3) Paths will be expanded
5
+ # 4) Paths will only be added if they don't already exist
6
+ #
7
+ module ::Kernel
8
+
9
+ # returns full path given relative to $LOAD_PATH
10
+ def require_which(aFilepath)
11
+ aFilepath += '.rb'
12
+ $LOAD_PATH.each do |dir|
13
+ full_path = File.expand_path(File.join(dir,aFilepath))
14
+ return full_path if File.exist? full_path
15
+ end
16
+ return nil
17
+ end
18
+
19
+ def require_paths(*aArgs)
20
+ caller_dir = File.dirname(File.expand_path(caller.first.sub(/:[0-9]+.*/,'')))
21
+ aArgs.each do |aPath|
22
+ aPath = File.expand_path(aPath,caller_dir)
23
+ $LOAD_PATH << aPath unless $LOAD_PATH.include?(aPath)
24
+ end
25
+ end
26
+
27
+ def require_paths_first(*aArgs)
28
+ caller_dir = File.dirname(File.expand_path(caller.first.sub(/:[0-9]+.*/,'')))
29
+ paths = []
30
+ aArgs.each do |aPath|
31
+ aPath = File.expand_path(aPath,caller_dir)
32
+ paths << aPath
33
+ end
34
+ paths.each do |p|
35
+ $LOAD_PATH.insert(0,p)
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,95 @@
1
+ module StringUtils
2
+ def self.crop(aString,aLength,aEllipsis=true,aConvertNil=true)
3
+ return aConvertNil ? ' '*aLength : nil if !aString
4
+
5
+ increase = aLength-aString.length
6
+ return aString+' '*increase if increase>=0
7
+ return aEllipsis ? aString[0,aLength-3]+'...' : aString[0,aLength]
8
+ end
9
+
10
+ def self.simplify_whitespace(aText)
11
+ aText.gsub(/[ \n\t\r]+/,' ').strip
12
+ end
13
+
14
+ def self.crop_to_word_count(aText,aWordCount)
15
+ aText = simplify_whitespace(aText)
16
+ matches = aText.scan_md(/[^\w-]+/)
17
+ match = matches[aWordCount-1]
18
+ result = (match ? match.pre_match : aText)
19
+ result
20
+ end
21
+
22
+ # aTemplate is a string containing tokens like ${SOME_TOKEN}
23
+ # aValues is a hash of token names eg. 'SOME_TOKEN' and their values to substitute
24
+ def self.render_template(aTemplate,aValues)
25
+ # get positions of tokens
26
+ result = aTemplate.gsub(/\$\{(.*?)\}/) do |s|
27
+ key = s[2..-2]
28
+ rep = (aValues[key] || s)
29
+ #puts "replacing #{s} with #{rep}"
30
+ rep
31
+ end
32
+ #puts "rendered :\n#{result}"
33
+ return result
34
+ end
35
+
36
+ def self.clean_number(aString)
37
+ aString.gsub(/[^0-9.-]/,'')
38
+ end
39
+
40
+ # supply a block with 2 parameters, and it will get called for each char as an integer
41
+ def self.each_unicode_char(aString)
42
+ len = 1
43
+ index = 0
44
+ char = 0
45
+ aString.each_byte do |b|
46
+ if index==0
47
+ len = 1
48
+ len = 2 if b & 0b11000000 != 0
49
+ len = 3 if b & 0b11100000 != 0
50
+ len = 4 if b & 0b11110000 != 0
51
+ char = 0
52
+ end
53
+
54
+ char |= b << index*8
55
+
56
+ yield(char,len) if index==len-1 # last byte; char is complete
57
+
58
+ index += 1
59
+ index = 0 if index >= len
60
+ end
61
+ end
62
+
63
+ # given ('abcdefg','c.*?e') returns ['ab','cde','fg'] so you can manipulate the head, match and tail seperately, and potentially rejoin
64
+ def self.split3(aString,aPattern,aOccurence=0)
65
+ matches = aString.scan_md(aPattern)
66
+ match = matches[aOccurence]
67
+ parts = (match ? [match.pre_match,match.to_s,match.post_match] : [aString,nil,''])
68
+
69
+ if !block_given? # return head,match,tail
70
+ parts
71
+ else # return string
72
+ parts[1] = yield *parts if match
73
+ parts.join
74
+ end
75
+ end
76
+
77
+ # truncates a string to the given length by looking for the previous space.
78
+ def self.word_safe_truncate(aString,aMaxLength)
79
+ return nil if !aString
80
+ return aString if aString.length <= aMaxLength
81
+ posLastSpace = aString.rindex(/[ \t]/,aMaxLength)
82
+ return aString[0,aMaxLength] if !posLastSpace
83
+ aString[0,posLastSpace]
84
+ end
85
+
86
+ # replaces all tabs with spaces, and reduces multiple spaces to a single space
87
+ def self.reduce_whitespace(aText)
88
+ aText = aText.gsub("\t"," ") # replace tabs with spaces
89
+ aText.strip!
90
+ aText.squeeze!(' ')
91
+ aText
92
+ end
93
+
94
+ end
95
+
@@ -0,0 +1,6 @@
1
+ # when you want to load the live version of buzzcorej, not the gem :
2
+ # require File.join(File.dirname(__FILE__),'../../../../../buzzcorej/lib/buzzcorej_dev.rb');
3
+ require File.join(File.dirname(__FILE__),'buzzcorej/require_paths') # load require_paths early for next line
4
+ require_paths_first '.'
5
+ require 'buzzcorej'
6
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buzzcorej
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - buzzware
@@ -42,9 +42,20 @@ extra_rdoc_files:
42
42
  - LICENSE
43
43
  - README.rdoc
44
44
  files:
45
- - lib/buzzcorej.rb
46
45
  - LICENSE
47
46
  - README.rdoc
47
+ - Rakefile
48
+ - VERSION
49
+ - buzzcorej.gemspec
50
+ - buzzcorej.vpj
51
+ - buzzcorej.vpw
52
+ - lib/buzzcorej.rb
53
+ - lib/buzzcorej/enum.rb
54
+ - lib/buzzcorej/extend_base_classes.rb
55
+ - lib/buzzcorej/misc_utils.rb
56
+ - lib/buzzcorej/require_paths.rb
57
+ - lib/buzzcorej/string_utils.rb
58
+ - lib/buzzcorej_dev.rb
48
59
  - test/test_helper.rb
49
60
  has_rdoc: true
50
61
  homepage: http://github.com/buzzware/buzzcorej