cldwalker-core 0.0.0
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/LICENSE.txt +22 -0
- data/README.markdown +80 -0
- data/Rakefile +49 -0
- data/VERSION.yml +4 -0
- data/lib/core/array.rb +105 -0
- data/lib/core/class.rb +18 -0
- data/lib/core/dir.rb +63 -0
- data/lib/core/file.rb +11 -0
- data/lib/core/hash.rb +81 -0
- data/lib/core/io.rb +21 -0
- data/lib/core/irb.rb +29 -0
- data/lib/core/object.rb +19 -0
- data/lib/core/string.rb +12 -0
- data/lib/core.rb +69 -0
- metadata +70 -0
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2008 Gabriel Horner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Description
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
My extensions to core and standard ruby 1.8 classes, similar to the facets and activesupport gems.
|
|
5
|
+
Although my extensions are probably nothing new, they are unobtrusive (monkeypatching is up to you)
|
|
6
|
+
and have basic checks for preventing method name collision.
|
|
7
|
+
So if you're not feeling shy, monkeypatch away:
|
|
8
|
+
|
|
9
|
+
irb>> require 'core'
|
|
10
|
+
true
|
|
11
|
+
irb>> Core.adds_to Array
|
|
12
|
+
Array
|
|
13
|
+
irb>> Core.ancestors
|
|
14
|
+
=> [Array, Core::Array, Enumerable, Object, PP::ObjectMixin, Kernel]
|
|
15
|
+
|
|
16
|
+
And if you're not feeling your monkey-fu:
|
|
17
|
+
|
|
18
|
+
irb>> class Base; class Array < Array; end; end
|
|
19
|
+
=> nil
|
|
20
|
+
irb>> Core.add_to Base::Array, :with=>Core::Array
|
|
21
|
+
=>Base::Array
|
|
22
|
+
irb>> Base::Array.ancestors
|
|
23
|
+
=>[Base::Array,Array, Core::Array, Enumerable, Object, PP::ObjectMixin, Kernel]
|
|
24
|
+
|
|
25
|
+
So what happens when it's four o'clock in the morning and you monkeypatch the wrong way?:
|
|
26
|
+
|
|
27
|
+
irb>> module Core::Array; def is_a?(*args); puts "dunno, i'm sleepy!"; end; end
|
|
28
|
+
nil
|
|
29
|
+
irb>> Core.adds_to Array
|
|
30
|
+
Couldn't include Core::Array into Array because the following methods conflict:
|
|
31
|
+
map
|
|
32
|
+
|
|
33
|
+
Phew, that was a close one. But wait, I really do think I know what I'm doing:
|
|
34
|
+
|
|
35
|
+
irb>> Core.adds_to Array, :force=>true
|
|
36
|
+
Array
|
|
37
|
+
irb>> [1,2].is_a?(Array)
|
|
38
|
+
dunno, i'm sleepy!
|
|
39
|
+
=>nil
|
|
40
|
+
|
|
41
|
+
Hopefully you'll use the force option more wisely.
|
|
42
|
+
|
|
43
|
+
Your Core
|
|
44
|
+
=========
|
|
45
|
+
If you'd like to wrap your own core extensions in say the original namespace MyCore:
|
|
46
|
+
|
|
47
|
+
MyCore.send :include, Core::Loader
|
|
48
|
+
|
|
49
|
+
You'll then be able to extend classes as in the examples above, replacing Core with MyCore.
|
|
50
|
+
To take advantage of the auto-requiring done by Core::Loader, place your extensions
|
|
51
|
+
in a directory mycore/ and make sure your $LOAD\_PATH contains the directory mycore.
|
|
52
|
+
In other words, `require 'mycore/array'` should be valid.
|
|
53
|
+
|
|
54
|
+
To wrap up your methods for MyCore, see my extensions or use this template:
|
|
55
|
+
|
|
56
|
+
#in mycore/array.rb
|
|
57
|
+
module MyCore
|
|
58
|
+
#extensions for Array's
|
|
59
|
+
module Array
|
|
60
|
+
def blah
|
|
61
|
+
end
|
|
62
|
+
#....
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
Limitations
|
|
68
|
+
===========
|
|
69
|
+
|
|
70
|
+
Checks for method name collisions currently use *instance\_methods and *methods of a class.
|
|
71
|
+
Patches for more thorough checks are welcome.
|
|
72
|
+
|
|
73
|
+
Todo
|
|
74
|
+
====
|
|
75
|
+
|
|
76
|
+
* Support extending class methods of the extended class.
|
|
77
|
+
* Import/Upgrade my old tests for my extension classes.
|
|
78
|
+
* Would be nice to:
|
|
79
|
+
** Provide aliasing for methods to avoid method name clashes.
|
|
80
|
+
** Make it easier to share/install core extensions made by others.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
begin
|
|
5
|
+
require 'rcov/rcovtask'
|
|
6
|
+
|
|
7
|
+
Rcov::RcovTask.new do |t|
|
|
8
|
+
t.libs << 'test'
|
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
|
10
|
+
t.rcov_opts = ["-T -x '/Library/Ruby/*'"]
|
|
11
|
+
t.verbose = true
|
|
12
|
+
end
|
|
13
|
+
rescue LoadError
|
|
14
|
+
puts "Rcov not available. Install it for rcov-related tasks with: sudo gem install rcov"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
require 'jeweler'
|
|
19
|
+
Jeweler::Tasks.new do |s|
|
|
20
|
+
s.name = "core"
|
|
21
|
+
s.description = "My extensions to core ruby classes, similar to the facets gem."
|
|
22
|
+
s.summary = s.description
|
|
23
|
+
s.email = "gabriel.horner@gmail.com"
|
|
24
|
+
s.homepage = "http://github.com/cldwalker/core"
|
|
25
|
+
s.authors = ["Gabriel Horner"]
|
|
26
|
+
s.files = FileList["VERSION.yml", "Rakefile", "README.markdown", "LICENSE.txt", "{bin,lib}/**/*"]
|
|
27
|
+
s.has_rdoc = true
|
|
28
|
+
s.extra_rdoc_files = ["README.markdown", "LICENSE.txt", "TODO.txt"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
rescue LoadError
|
|
32
|
+
puts "Jeweler not available. Install it for jeweler-related tasks with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Rake::TestTask.new do |t|
|
|
36
|
+
t.libs << 'lib'
|
|
37
|
+
t.pattern = 'test/**/*_test.rb'
|
|
38
|
+
t.verbose = false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
43
|
+
rdoc.title = 'test'
|
|
44
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
45
|
+
rdoc.rdoc_files.include('README*')
|
|
46
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
task :default => :test
|
data/VERSION.yml
ADDED
data/lib/core/array.rb
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Core
|
|
2
|
+
module Array
|
|
3
|
+
# Allows you to specify ranges of elements and individual elements with one string, array starts at 1
|
|
4
|
+
# Example: choose first and fourth through eighth elements: '1,4-8'
|
|
5
|
+
def multislice(range,splitter=',',offset=nil)
|
|
6
|
+
#td: fix swallowing of empty lines
|
|
7
|
+
result = []
|
|
8
|
+
for r in range.split(splitter)
|
|
9
|
+
if r =~ /-/
|
|
10
|
+
min,max = r.split('-')
|
|
11
|
+
slice_min = min.to_i - 1
|
|
12
|
+
slice_min += offset if offset
|
|
13
|
+
result.push(*self.slice(slice_min, max.to_i - min.to_i + 1))
|
|
14
|
+
else
|
|
15
|
+
index = r.to_i - 1
|
|
16
|
+
index += offset if offset
|
|
17
|
+
result.push(self[index])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
return result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Converts an even # of array elements ie [1,2,3,4]
|
|
24
|
+
# or an array of array pairs ie [[1,2],[3,4]] to a hash.
|
|
25
|
+
def to_hash
|
|
26
|
+
Hash[*self.flatten]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns hash mapping elements to the number of times they are found in the array.
|
|
30
|
+
def count_hash
|
|
31
|
+
count = {}
|
|
32
|
+
each {|e|
|
|
33
|
+
count[e] ||= 0
|
|
34
|
+
count[e] += 1
|
|
35
|
+
}
|
|
36
|
+
count
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns all possible paired permutations of elements disregarding order.
|
|
40
|
+
def permute
|
|
41
|
+
permutations = []
|
|
42
|
+
for i in (0 .. self.size - 1)
|
|
43
|
+
for j in (i + 1 .. self.size - 1)
|
|
44
|
+
permutations.push([self[i],self[j]])
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
permutations
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Assuming the array is an array of hashes, this returns a hash of the elements grouped by their
|
|
51
|
+
# values for the specified hash key.
|
|
52
|
+
def group_aoh_by_key(key,parallel_array=nil)
|
|
53
|
+
group = {}
|
|
54
|
+
each_with_index {|h,i|
|
|
55
|
+
value = h[key]
|
|
56
|
+
group[value] = [] if ! group.has_key?(value)
|
|
57
|
+
group[value].push((parallel_array.nil?) ? h : parallel_array[i])
|
|
58
|
+
}
|
|
59
|
+
group
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Maps the result of calling each element with the given method name and optional arguments.
|
|
63
|
+
def mmap(methodname,*args)
|
|
64
|
+
map {|e| e.send(methodname,*args) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Maps the result of calling the given function name with each element as its argument.
|
|
68
|
+
def fmap(function)
|
|
69
|
+
(function =~ /\./) ?
|
|
70
|
+
map {|e| eval "#{function}(e)" } :
|
|
71
|
+
map {|e| send(function,e) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns index of first element to match given regular expression.
|
|
75
|
+
def regindex(regex)
|
|
76
|
+
each_with_index {|e,i|
|
|
77
|
+
return i if e =~ /#{regex}/
|
|
78
|
+
}
|
|
79
|
+
nil
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Replaces element at index with values of given array.
|
|
83
|
+
def replace_index(i,array)
|
|
84
|
+
replace( (self[0, i] || []) + array + self[i + 1 .. -1] )
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns true if the array includes any from the first array and excludes all from the second.
|
|
88
|
+
def include_and_exclude?(do_include,dont_include=[])
|
|
89
|
+
include_any?(do_include) && exclude_all?(dont_include)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Returns true if it has any elements in common with the given array.
|
|
93
|
+
def include_any?(arr)
|
|
94
|
+
#good for large sets w/ few matches
|
|
95
|
+
#! Set.new(self).intersection(arr).empty?
|
|
96
|
+
arr.any? {|e| self.include?(e) }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# Returns true if it has no elements in common with the given array.
|
|
101
|
+
def exclude_all?(arr)
|
|
102
|
+
! include_any?(arr)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
data/lib/core/class.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Class
|
|
2
|
+
# Returns ancestors that aren't included modules and the class itself.
|
|
3
|
+
def real_ancestors
|
|
4
|
+
ancestors - included_modules - [self]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
#Returns all objects of class.
|
|
8
|
+
def objects
|
|
9
|
+
object = []
|
|
10
|
+
ObjectSpace.each_object(self) {|e| object.push(e) }
|
|
11
|
+
object
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#td: used to be :objects, change tb_* files to reflect change
|
|
15
|
+
def object_strings #:nodoc:
|
|
16
|
+
objects.map {|e| e.to_s}
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/core/dir.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# All methods here take an optional directory argument, defaulting to the current directory.
|
|
2
|
+
class Dir
|
|
3
|
+
# Returns current directory with a '/' appended.
|
|
4
|
+
def self.mpwd
|
|
5
|
+
Dir.pwd + "/"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Returns entries from simple_entries() that are directories.
|
|
9
|
+
def self.dir_children(dirname=mpwd)
|
|
10
|
+
self.simple_entries(dirname).find_all {|e|
|
|
11
|
+
File.directory?(File.join(dirname, e))
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Returns entries from simple_entries() that are files.
|
|
16
|
+
def self.file_children(dirname=mpwd)
|
|
17
|
+
self.simple_entries(dirname).find_all {|e|
|
|
18
|
+
File.file?(File.join(dirname,e))
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns everything in a directory that entries() would except
|
|
23
|
+
# for '.', '..' and vim's backup files ie files ending with ~ or .sw*.
|
|
24
|
+
# You should override this method to take advantage of methods based on it.
|
|
25
|
+
def self.simple_entries(dirname=mpwd)
|
|
26
|
+
dir_files = Dir.entries(dirname)
|
|
27
|
+
files = dir_files - ['.','..'] - dir_files.grep(/~$/) - dir_files.grep(/\.sw[o-z]$/)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns entries from simple_entries() that are not symlinks.
|
|
31
|
+
def self.nonlink_entries(dirname=mpwd)
|
|
32
|
+
self.simple_entries(dirname).select {|e|
|
|
33
|
+
! File.symlink?(File.join(dirname,e))
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#Returns the full paths of simple_entries().
|
|
38
|
+
def self.full_entries(dirname=mpwd)
|
|
39
|
+
self.simple_entries(dirname).map {|e| File.join(dirname,e) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns all simple_entries under a directory for the specified depth. If no depth specified
|
|
43
|
+
# it'll return all entries under the directory.
|
|
44
|
+
def self.levels_of_children(dirname=mpwd,max_level=1000)
|
|
45
|
+
@max_level = max_level
|
|
46
|
+
@level_children = []
|
|
47
|
+
self.get_level_children(dirname,0)
|
|
48
|
+
@level_children
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#used recursively by levels_of_children
|
|
52
|
+
def self.get_level_children(dirname,level) #:nodoc:
|
|
53
|
+
dir_children = self.full_entries(dirname)
|
|
54
|
+
@level_children += dir_children
|
|
55
|
+
if level < @max_level
|
|
56
|
+
dir_children.each {|e|
|
|
57
|
+
if File.directory?(e)
|
|
58
|
+
self.get_level_children(e,level + 1)
|
|
59
|
+
end
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/core/file.rb
ADDED
data/lib/core/hash.rb
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
class Hash
|
|
2
|
+
# For a hash whose keys are strings of Class names, this will delete any pairs that have
|
|
3
|
+
# nonexistant class names.
|
|
4
|
+
def validate_value_klass(klass)
|
|
5
|
+
self.each {|sid,obj|
|
|
6
|
+
if obj.class != Object.const_get(klass)
|
|
7
|
+
warn "object of '#{sid}' not a #{klass}"
|
|
8
|
+
self.delete(sid)
|
|
9
|
+
end
|
|
10
|
+
}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns a hash which will set its values by calling each value with the given method and optional argument.
|
|
14
|
+
# If a block is passed, each value will be set the value returned by its block call.
|
|
15
|
+
def vmap(arg=nil,method='[]',&block)
|
|
16
|
+
new = {}
|
|
17
|
+
if block
|
|
18
|
+
self.each {|k,v|
|
|
19
|
+
v1 = yield(k,v)
|
|
20
|
+
new[k] = v1
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
self.each {|k,v|
|
|
24
|
+
new[k] = arg.nil? ? v.send(method) : v.send(method,arg)
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Same as vmap() but merges its results with the existing hash.
|
|
31
|
+
def vmap!(*args,&block)
|
|
32
|
+
self.update(vmap(*args,&block))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# For a hash whose values are arrays, this will return a hash with each value substituted by the
|
|
36
|
+
# size of the value.
|
|
37
|
+
def vsize
|
|
38
|
+
vmap(nil,'size')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Same as pass_keys!() but replaces the hash with the resulting hash.
|
|
42
|
+
def only_keep(arr=[],opt={})
|
|
43
|
+
delete_keys!(self.keys - arr,opt)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def delete_keys!(arr=[],opt={}) #:nodoc:
|
|
47
|
+
deleted = {}
|
|
48
|
+
arr.each {|e|
|
|
49
|
+
puts "deleting #{e}" if opt[:verbose]
|
|
50
|
+
deleted[e] = self.delete(e) if has_key?(e)
|
|
51
|
+
}
|
|
52
|
+
deleted
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns a subset of the hash for the specified keys. These entries will be deleted from the
|
|
56
|
+
# original hash.
|
|
57
|
+
def pass_keys!(*keys)
|
|
58
|
+
delete_keys!(keys)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# For a hash whose values are arrays, this will set each unique element in a value array as a key
|
|
62
|
+
# and set its values to all the keys it occurred in.
|
|
63
|
+
# This is useful when modeling one to many relationships with keys
|
|
64
|
+
# and values.
|
|
65
|
+
def transform_many
|
|
66
|
+
b = {}
|
|
67
|
+
each {|k,arr|
|
|
68
|
+
#raise "#{arr.inspect} not an Array" if arr.class != Array
|
|
69
|
+
arr = [arr] if arr.class != Array
|
|
70
|
+
arr.each {|e|
|
|
71
|
+
b.has_key?(e) ? b[e].push(k) : b[e] = [k]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
b
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#Sorts hash by values, returning them as an array of array pairs.
|
|
78
|
+
def vsort
|
|
79
|
+
sort { |a,b| b[1]<=>a[1] }
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/core/io.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class IO
|
|
2
|
+
#Returns array of lines up until the given string matches a line of the file.
|
|
3
|
+
def self.read_until(file,string)
|
|
4
|
+
f = self.readlines(file)
|
|
5
|
+
i = f.index(string) || 100000
|
|
6
|
+
f.slice(0,i)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
#from output_catcher gem
|
|
10
|
+
def self.capture_stdout(&block)
|
|
11
|
+
original_stdout = $stdout
|
|
12
|
+
$stdout = fake = StringIO.new
|
|
13
|
+
begin
|
|
14
|
+
yield
|
|
15
|
+
ensure
|
|
16
|
+
$stdout = original_stdout
|
|
17
|
+
end
|
|
18
|
+
fake.string
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
data/lib/core/irb.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#from http://errtheblog.com/posts/9-drop-to-irb
|
|
2
|
+
# call with IRB.start_session(Kernel.binding) in script
|
|
3
|
+
require 'irb'
|
|
4
|
+
|
|
5
|
+
module IRB
|
|
6
|
+
def self.start_session(binding)
|
|
7
|
+
IRB.setup(nil)
|
|
8
|
+
|
|
9
|
+
workspace = WorkSpace.new(binding)
|
|
10
|
+
|
|
11
|
+
if @CONF[:SCRIPT]
|
|
12
|
+
irb = Irb.new(workspace, @CONF[:SCRIPT])
|
|
13
|
+
else
|
|
14
|
+
irb = Irb.new(workspace)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
|
|
18
|
+
@CONF[:MAIN_CONTEXT] = irb.context
|
|
19
|
+
|
|
20
|
+
trap("SIGINT") do
|
|
21
|
+
irb.signal_handle
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
catch(:IRB_EXIT) do
|
|
25
|
+
irb.eval_input
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
data/lib/core/object.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
# A more versatile for of Object.const_get.
|
|
3
|
+
# Retrieves constant for given string, even if it's nested under classes.
|
|
4
|
+
def self.any_const_get(name)
|
|
5
|
+
begin
|
|
6
|
+
klass = Object
|
|
7
|
+
name.split('::').each {|e|
|
|
8
|
+
klass = klass.const_get(e)
|
|
9
|
+
}
|
|
10
|
+
klass
|
|
11
|
+
rescue; nil; end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#Reloads a file just as you would require it.
|
|
15
|
+
def reload(filename)
|
|
16
|
+
$".delete(filename + ".rb")
|
|
17
|
+
require(filename)
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/core/string.rb
ADDED
data/lib/core.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
|
3
|
+
module Core
|
|
4
|
+
module Loader
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(self)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def adds_to(klass, options = {})
|
|
10
|
+
unless (extension_klass = options[:with] || get_extension_class(klass))
|
|
11
|
+
puts "No #{self} extension class found"
|
|
12
|
+
return false
|
|
13
|
+
end
|
|
14
|
+
conflicts = check_for_conflicts(klass, extension_klass)
|
|
15
|
+
if conflicts.empty? || options[:force]
|
|
16
|
+
klass.send :include, extension_klass
|
|
17
|
+
else
|
|
18
|
+
puts "Couldn't include #{extension_klass} into #{klass} because the following methods conflict:"
|
|
19
|
+
puts conflicts.sort.join(", ")
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
alias_method :add_to, :adds_to
|
|
24
|
+
|
|
25
|
+
def detect_extension_class(klass)
|
|
26
|
+
extension_klass = self.const_get(klass.to_s) rescue nil
|
|
27
|
+
extension_klass = nil if extension_klass == klass
|
|
28
|
+
extension_klass
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def get_extension_class(klass)
|
|
32
|
+
unless (extension_klass = detect_extension_class(klass))
|
|
33
|
+
#try again but first by requiring possible file
|
|
34
|
+
begin; require("#{self.to_s.gsub('::','/').downcase}/#{klass.to_s.downcase}"); rescue(LoadError); end
|
|
35
|
+
extension_klass = detect_extension_class(klass)
|
|
36
|
+
end
|
|
37
|
+
extension_klass
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def check_for_conflicts(klass, extension_klass)
|
|
41
|
+
if false #TODO: extension_klass.to_s =~ /ClassMethods/
|
|
42
|
+
else
|
|
43
|
+
all_instance_methods(klass) & all_instance_methods(extension_klass)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def all_instance_methods(klass)
|
|
48
|
+
klass.public_instance_methods + klass.private_instance_methods + klass.protected_instance_methods
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Core.send :include, Core::Loader
|
|
54
|
+
|
|
55
|
+
__END__
|
|
56
|
+
|
|
57
|
+
#extend Array with Core::Array's ClassMethods + InstanceMethods
|
|
58
|
+
Core.adds_to Array
|
|
59
|
+
|
|
60
|
+
#extend MyArray from file
|
|
61
|
+
class My::Array
|
|
62
|
+
Core.adds_to self
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#from console
|
|
66
|
+
Core.adds_to My::Array
|
|
67
|
+
|
|
68
|
+
#extend Array only with ClassMethods
|
|
69
|
+
Core.adds_to Array, :from=>Core::Array::ClassMethods
|
metadata
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cldwalker-core
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gabriel Horner
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-01-28 00:00:00 -08:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies: []
|
|
15
|
+
|
|
16
|
+
description: My extensions to core ruby classes, similar to the facets gem.
|
|
17
|
+
email: gabriel.horner@gmail.com
|
|
18
|
+
executables: []
|
|
19
|
+
|
|
20
|
+
extensions: []
|
|
21
|
+
|
|
22
|
+
extra_rdoc_files:
|
|
23
|
+
- README.markdown
|
|
24
|
+
- LICENSE.txt
|
|
25
|
+
- TODO.txt
|
|
26
|
+
files:
|
|
27
|
+
- VERSION.yml
|
|
28
|
+
- Rakefile
|
|
29
|
+
- README.markdown
|
|
30
|
+
- LICENSE.txt
|
|
31
|
+
- lib/core
|
|
32
|
+
- lib/core/array.rb
|
|
33
|
+
- lib/core/class.rb
|
|
34
|
+
- lib/core/dir.rb
|
|
35
|
+
- lib/core/file.rb
|
|
36
|
+
- lib/core/hash.rb
|
|
37
|
+
- lib/core/io.rb
|
|
38
|
+
- lib/core/irb.rb
|
|
39
|
+
- lib/core/object.rb
|
|
40
|
+
- lib/core/string.rb
|
|
41
|
+
- lib/core.rb
|
|
42
|
+
- TODO.txt
|
|
43
|
+
has_rdoc: true
|
|
44
|
+
homepage: http://github.com/cldwalker/core
|
|
45
|
+
post_install_message:
|
|
46
|
+
rdoc_options: []
|
|
47
|
+
|
|
48
|
+
require_paths:
|
|
49
|
+
- lib
|
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: "0"
|
|
55
|
+
version:
|
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: "0"
|
|
61
|
+
version:
|
|
62
|
+
requirements: []
|
|
63
|
+
|
|
64
|
+
rubyforge_project:
|
|
65
|
+
rubygems_version: 1.2.0
|
|
66
|
+
signing_key:
|
|
67
|
+
specification_version: 2
|
|
68
|
+
summary: My extensions to core ruby classes, similar to the facets gem.
|
|
69
|
+
test_files: []
|
|
70
|
+
|