buzzcorej 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +63 -0
- data/VERSION +2 -0
- data/buzzcorej.gemspec +58 -0
- data/buzzcorej.vpj +93 -0
- data/buzzcorej.vpw +93 -0
- data/lib/buzzcorej/enum.rb +50 -0
- data/lib/buzzcorej/extend_base_classes.rb +485 -0
- data/lib/buzzcorej/misc_utils.rb +334 -0
- data/lib/buzzcorej/require_paths.rb +39 -0
- data/lib/buzzcorej/string_utils.rb +95 -0
- data/lib/buzzcorej_dev.rb +6 -0
- metadata +15 -4
data/Rakefile
ADDED
|
@@ -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
data/buzzcorej.gemspec
ADDED
|
@@ -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
|
+
|
data/buzzcorej.vpj
ADDED
|
@@ -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="&Compile"
|
|
14
|
+
CaptureOutputWith="ProcessBuffer"
|
|
15
|
+
SaveOption="SaveCurrent"
|
|
16
|
+
RunFromDir="%rw">
|
|
17
|
+
<Exec/>
|
|
18
|
+
</Target>
|
|
19
|
+
<Target
|
|
20
|
+
Name="Build"
|
|
21
|
+
MenuCaption="&Build"
|
|
22
|
+
CaptureOutputWith="ProcessBuffer"
|
|
23
|
+
SaveOption="SaveWorkspaceFiles"
|
|
24
|
+
RunFromDir="%rw">
|
|
25
|
+
<Exec/>
|
|
26
|
+
</Target>
|
|
27
|
+
<Target
|
|
28
|
+
Name="Rebuild"
|
|
29
|
+
MenuCaption="&Rebuild"
|
|
30
|
+
CaptureOutputWith="ProcessBuffer"
|
|
31
|
+
SaveOption="SaveWorkspaceFiles"
|
|
32
|
+
RunFromDir="%rw">
|
|
33
|
+
<Exec/>
|
|
34
|
+
</Target>
|
|
35
|
+
<Target
|
|
36
|
+
Name="Debug"
|
|
37
|
+
MenuCaption="&Debug"
|
|
38
|
+
SaveOption="SaveNone"
|
|
39
|
+
RunFromDir="%rw">
|
|
40
|
+
<Exec/>
|
|
41
|
+
</Target>
|
|
42
|
+
<Target
|
|
43
|
+
Name="Execute"
|
|
44
|
+
MenuCaption="E&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>
|
data/buzzcorej.vpw
ADDED
|
@@ -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="&Compile"
|
|
14
|
+
CaptureOutputWith="ProcessBuffer"
|
|
15
|
+
SaveOption="SaveCurrent"
|
|
16
|
+
RunFromDir="%rw">
|
|
17
|
+
<Exec/>
|
|
18
|
+
</Target>
|
|
19
|
+
<Target
|
|
20
|
+
Name="Build"
|
|
21
|
+
MenuCaption="&Build"
|
|
22
|
+
CaptureOutputWith="ProcessBuffer"
|
|
23
|
+
SaveOption="SaveWorkspaceFiles"
|
|
24
|
+
RunFromDir="%rw">
|
|
25
|
+
<Exec/>
|
|
26
|
+
</Target>
|
|
27
|
+
<Target
|
|
28
|
+
Name="Rebuild"
|
|
29
|
+
MenuCaption="&Rebuild"
|
|
30
|
+
CaptureOutputWith="ProcessBuffer"
|
|
31
|
+
SaveOption="SaveWorkspaceFiles"
|
|
32
|
+
RunFromDir="%rw">
|
|
33
|
+
<Exec/>
|
|
34
|
+
</Target>
|
|
35
|
+
<Target
|
|
36
|
+
Name="Debug"
|
|
37
|
+
MenuCaption="&Debug"
|
|
38
|
+
SaveOption="SaveNone"
|
|
39
|
+
RunFromDir="%rw">
|
|
40
|
+
<Exec/>
|
|
41
|
+
</Target>
|
|
42
|
+
<Target
|
|
43
|
+
Name="Execute"
|
|
44
|
+
MenuCaption="E&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:
|
|
4
|
+
hash: 27
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 0.0.
|
|
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
|