epitools 0.5.8 → 0.5.9
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/VERSION +1 -1
- data/epitools.gemspec +4 -2
- data/lib/epitools.rb +2 -116
- data/lib/epitools/core_ext.rb +3 -245
- data/lib/epitools/core_ext/misc.rb +224 -0
- data/lib/epitools/minimal.rb +143 -0
- data/lib/epitools/path.rb +3 -1
- data/lib/epitools/sys.rb +1 -1
- data/lib/epitools/typed_struct.rb +12 -9
- data/lib/epitools/wm.rb +11 -2
- data/spec/autoreq_spec.rb +1 -1
- data/spec/path_spec.rb +1 -1
- data/spec/wm_spec.rb +9 -2
- metadata +4 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.9
|
data/epitools.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "epitools"
|
8
|
-
s.version = "0.5.
|
8
|
+
s.version = "0.5.9"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["epitron"]
|
12
|
-
s.date = "2012-07-
|
12
|
+
s.date = "2012-07-09"
|
13
13
|
s.description = "Miscellaneous utility libraries to make my life easier."
|
14
14
|
s.email = "chris@ill-logic.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -37,6 +37,7 @@ Gem::Specification.new do |s|
|
|
37
37
|
"lib/epitools/core_ext/array.rb",
|
38
38
|
"lib/epitools/core_ext/enumerable.rb",
|
39
39
|
"lib/epitools/core_ext/hash.rb",
|
40
|
+
"lib/epitools/core_ext/misc.rb",
|
40
41
|
"lib/epitools/core_ext/numbers.rb",
|
41
42
|
"lib/epitools/core_ext/object.rb",
|
42
43
|
"lib/epitools/core_ext/string.rb",
|
@@ -48,6 +49,7 @@ Gem::Specification.new do |s|
|
|
48
49
|
"lib/epitools/lcs.rb",
|
49
50
|
"lib/epitools/mimemagic.rb",
|
50
51
|
"lib/epitools/mimemagic_tables.rb",
|
52
|
+
"lib/epitools/minimal.rb",
|
51
53
|
"lib/epitools/niceprint.rb",
|
52
54
|
"lib/epitools/numwords.rb",
|
53
55
|
"lib/epitools/path.rb",
|
data/lib/epitools.rb
CHANGED
@@ -1,120 +1,7 @@
|
|
1
1
|
require 'pp'
|
2
|
+
require File.join(File.dirname(__FILE__), "epitools", "minimal")
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
unless defined?(__DIR__)
|
6
|
-
#
|
7
|
-
# This method is convenience for the `File.expand_path(File.dirname(__FILE__))` idiom.
|
8
|
-
# (taken from Michael Fellinger's Ramaze... thanx, dood! :D)
|
9
|
-
#
|
10
|
-
def __DIR__(*args)
|
11
|
-
filename = caller[0][/^(.*):/, 1]
|
12
|
-
dir = File.expand_path(File.dirname(filename))
|
13
|
-
::File.expand_path(::File.join(dir, *args.map{|a| a.to_s}))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
#
|
18
|
-
# 'autoreq' is a replacement for autoload that can load gems.
|
19
|
-
#
|
20
|
-
# Usage:
|
21
|
-
# autoreq :Constant, 'thing-to-require'
|
22
|
-
# autoreq :Constant, 'thing-to-require'
|
23
|
-
# autoreq :OtherConstant do
|
24
|
-
# gem 'somegem', '~> 1.2'
|
25
|
-
# require 'somegem'
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
def autoreq(const, path=nil, &block)
|
29
|
-
raise "Error: autoreq must be supplied with a file to load, or a block." unless !!path ^ block_given?
|
30
|
-
|
31
|
-
if block_given?
|
32
|
-
Module.autoreqs[const] = block
|
33
|
-
else
|
34
|
-
Module.autoreqs[const] = path
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
#
|
39
|
-
# Remove an object, method, constant, etc.
|
40
|
-
#
|
41
|
-
def del(x)
|
42
|
-
case x
|
43
|
-
when String
|
44
|
-
del(x.to_sym)
|
45
|
-
when Class, Module
|
46
|
-
Object.send(:remove_const, x.name)
|
47
|
-
when Method
|
48
|
-
x.owner.send(:undef_method, x.name)
|
49
|
-
when Symbol
|
50
|
-
if Object.const_get(x)
|
51
|
-
Object.send(:remove_const, x)
|
52
|
-
elsif method(x)
|
53
|
-
undef_method x
|
54
|
-
end
|
55
|
-
else
|
56
|
-
raise "Error: don't know how to 'del #{x.inspect}'"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# The hidden singleton lurks behind everyone
|
61
|
-
def metaclass
|
62
|
-
class << self
|
63
|
-
self
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def meta_eval &blk
|
68
|
-
metaclass.instance_eval &blk
|
69
|
-
end
|
70
|
-
|
71
|
-
# Adds methods to a metaclass
|
72
|
-
def meta_def name, &blk
|
73
|
-
meta_eval { define_method name, &blk }
|
74
|
-
end
|
75
|
-
|
76
|
-
# Defines an instance method within a class
|
77
|
-
def class_def name, &blk
|
78
|
-
class_eval { define_method name, &blk }
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
#
|
84
|
-
# Patch 'Module#const_missing' to support 'autoreq' (which can autoload gems)
|
85
|
-
#
|
86
|
-
class Module
|
87
|
-
|
88
|
-
@@autoreq_is_searching_for = nil
|
89
|
-
|
90
|
-
alias const_missing_without_autoreq const_missing
|
91
|
-
|
92
|
-
def const_missing(const)
|
93
|
-
return if const == @@autoreq_is_searching_for
|
94
|
-
|
95
|
-
if thing = autoreqs[const]
|
96
|
-
case thing
|
97
|
-
when String, Symbol
|
98
|
-
require thing
|
99
|
-
when Proc
|
100
|
-
Object.class_eval(&thing)
|
101
|
-
else
|
102
|
-
raise "Error: Don't know how to autoload a #{thing.class}: #{thing.inspect}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
@@autoreq_is_searching_for = const
|
107
|
-
const_get(const) || const_missing_without_autoreq(const)
|
108
|
-
end
|
109
|
-
|
110
|
-
def autoreqs
|
111
|
-
@@autoreqs ||= {}
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
## Pretty error messages
|
4
|
+
## Pretty loading messages
|
118
5
|
require_wrapper = proc do |mod|
|
119
6
|
#p [:loading, mod]
|
120
7
|
begin
|
@@ -128,7 +15,6 @@ end
|
|
128
15
|
# Make all the modules autoload, and require all the monkeypatches
|
129
16
|
#
|
130
17
|
%w[
|
131
|
-
autoloads
|
132
18
|
core_ext
|
133
19
|
zopen
|
134
20
|
colored
|
data/lib/epitools/core_ext.rb
CHANGED
@@ -1,32 +1,6 @@
|
|
1
1
|
require 'epitools'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
if RUBY_VERSION["1.8"]
|
6
|
-
require 'enumerator'
|
7
|
-
Enumerator = Enumerable::Enumerator unless defined? Enumerator
|
8
|
-
end
|
9
|
-
|
10
|
-
unless defined? Enum
|
11
|
-
if defined? Enumerator
|
12
|
-
Enum = Enumerator
|
13
|
-
else
|
14
|
-
$stderr.puts "WARNING: Couldn't find the Enumerator class. Enum will not be available."
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
RbConfig = Config unless defined? RbConfig
|
19
|
-
|
20
|
-
|
21
|
-
class Object
|
22
|
-
#
|
23
|
-
# Slightly gross hack to add a class method.
|
24
|
-
#
|
25
|
-
def self.alias_class_method(dest, src)
|
26
|
-
metaclass.send(:alias_method, dest, src)
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
3
|
+
##############################################################################
|
30
4
|
|
31
5
|
require 'epitools/core_ext/object'
|
32
6
|
require 'epitools/core_ext/string'
|
@@ -35,223 +9,7 @@ require 'epitools/core_ext/enumerable'
|
|
35
9
|
require 'epitools/core_ext/hash'
|
36
10
|
require 'epitools/core_ext/numbers'
|
37
11
|
require 'epitools/core_ext/truthiness'
|
12
|
+
require 'epitools/core_ext/misc'
|
38
13
|
|
14
|
+
##############################################################################
|
39
15
|
|
40
|
-
class MatchData
|
41
|
-
|
42
|
-
#
|
43
|
-
# Return a hash of named matches
|
44
|
-
#
|
45
|
-
def to_hash
|
46
|
-
Hash[ names.zip(captures) ]
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
class Binding
|
53
|
-
|
54
|
-
#
|
55
|
-
# Get a variables in this binding
|
56
|
-
#
|
57
|
-
def [](key)
|
58
|
-
eval(key.to_s)
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# Set a variable in this binding
|
63
|
-
#
|
64
|
-
def []=(key, val)
|
65
|
-
Thread.current[:_alter_binding_local_] = val
|
66
|
-
eval("#{key} = Thread.current[:_alter_binding_local_]")
|
67
|
-
Thread.current[:_alter_binding_local_] = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
#
|
71
|
-
# Return all the local variables in the binding
|
72
|
-
#
|
73
|
-
def local_variables
|
74
|
-
eval("local_variables")
|
75
|
-
end
|
76
|
-
alias_method :keys, :local_variables
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
class Proc
|
82
|
-
|
83
|
-
#
|
84
|
-
# Chain two procs together, returning a new proc. Each proc is executed one after the other,
|
85
|
-
# with the same input arguments. The return value is an array of all the procs' return values.
|
86
|
-
#
|
87
|
-
# You can use either the .join method, or the overloaded & operator.
|
88
|
-
#
|
89
|
-
# Examples:
|
90
|
-
# joined = proc1 & proc2
|
91
|
-
# joined = proc1.join proc2
|
92
|
-
# newproc = proc { 1 } & proc { 2 }
|
93
|
-
# newproc.call #=> [1, 2]
|
94
|
-
#
|
95
|
-
def join(other=nil, &block)
|
96
|
-
other ||= block
|
97
|
-
proc { |*args| [self.call(*args), other.call(*args)] }
|
98
|
-
end
|
99
|
-
alias_method :&, :join
|
100
|
-
|
101
|
-
#
|
102
|
-
# Chains two procs together, returning a new proc. The output from each proc is passed into
|
103
|
-
# the input of the next one.
|
104
|
-
#
|
105
|
-
# Example:
|
106
|
-
# chain = proc { 1 } | proc { |input| input + 1 }
|
107
|
-
# chain.call #=> 2
|
108
|
-
#
|
109
|
-
def chain(other=nil, &block)
|
110
|
-
other ||= block
|
111
|
-
proc { |*args| other.call( self.call(*args) ) }
|
112
|
-
end
|
113
|
-
alias_method :|, :chain
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
unless defined?(BasicObject)
|
119
|
-
#
|
120
|
-
# Backported BasicObject for Ruby 1.8
|
121
|
-
#
|
122
|
-
class BasicObject
|
123
|
-
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
class Object
|
130
|
-
|
131
|
-
#
|
132
|
-
# Negates a boolean, chained-method style.
|
133
|
-
#
|
134
|
-
# Example:
|
135
|
-
# >> 10.even?
|
136
|
-
# => true
|
137
|
-
# >> 10.not.even?
|
138
|
-
# => false
|
139
|
-
#
|
140
|
-
def not
|
141
|
-
NotWrapper.new(self)
|
142
|
-
end
|
143
|
-
|
144
|
-
end
|
145
|
-
|
146
|
-
class NotWrapper < BasicObject # :nodoc:
|
147
|
-
def initialize(orig)
|
148
|
-
@orig = orig
|
149
|
-
end
|
150
|
-
|
151
|
-
def inspect
|
152
|
-
"{NOT #{@orig.inspect}}"
|
153
|
-
end
|
154
|
-
|
155
|
-
def is_a?(other)
|
156
|
-
other === self
|
157
|
-
end
|
158
|
-
|
159
|
-
def method_missing(meth, *args, &block)
|
160
|
-
result = @orig.send(meth, *args, &block)
|
161
|
-
if result.is_a? ::TrueClass or result.is_a? ::FalseClass
|
162
|
-
!result
|
163
|
-
else
|
164
|
-
raise "Sorry, I don't know how to invert #{result.inspect}"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
unless IO.respond_to? :copy_stream
|
172
|
-
|
173
|
-
class IO
|
174
|
-
|
175
|
-
#
|
176
|
-
# IO.copy_stream backport
|
177
|
-
#
|
178
|
-
def self.copy_stream(input, output)
|
179
|
-
while chunk = input.read(8192)
|
180
|
-
output.write(chunk)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
|
-
|
189
|
-
class Range
|
190
|
-
|
191
|
-
#
|
192
|
-
# Pick a random number from the range.
|
193
|
-
#
|
194
|
-
def rand
|
195
|
-
Kernel.rand(self)
|
196
|
-
end
|
197
|
-
|
198
|
-
end
|
199
|
-
|
200
|
-
|
201
|
-
class Struct
|
202
|
-
|
203
|
-
#
|
204
|
-
# Transform this struct into a JSON hash
|
205
|
-
#
|
206
|
-
def to_hash
|
207
|
-
hash = {}
|
208
|
-
each_pair { |k,v| hash[k] = v }
|
209
|
-
hash
|
210
|
-
end
|
211
|
-
|
212
|
-
#
|
213
|
-
# Transform the struct into a simple JSON hash.
|
214
|
-
#
|
215
|
-
def to_json(*args)
|
216
|
-
to_hash.to_json
|
217
|
-
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
|
222
|
-
module URI
|
223
|
-
|
224
|
-
#
|
225
|
-
# Return a Hash of the variables in the query string
|
226
|
-
#
|
227
|
-
def params
|
228
|
-
query.to_params
|
229
|
-
end
|
230
|
-
|
231
|
-
end
|
232
|
-
|
233
|
-
|
234
|
-
class Time
|
235
|
-
|
236
|
-
#
|
237
|
-
# Which "quarter" of the year does this date fall into?
|
238
|
-
#
|
239
|
-
def quarter
|
240
|
-
(month / 3.0).ceil
|
241
|
-
end
|
242
|
-
|
243
|
-
end
|
244
|
-
|
245
|
-
|
246
|
-
#
|
247
|
-
# Give ObjectSpace Enumerable powers (select, map, etc.)
|
248
|
-
#
|
249
|
-
module ObjectSpace
|
250
|
-
|
251
|
-
include Enumerable
|
252
|
-
|
253
|
-
alias_method :each, :each_object
|
254
|
-
|
255
|
-
extend self
|
256
|
-
|
257
|
-
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
class MatchData
|
2
|
+
|
3
|
+
#
|
4
|
+
# Return a hash of named matches
|
5
|
+
#
|
6
|
+
def to_hash
|
7
|
+
Hash[ names.zip(captures) ]
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
class Binding
|
13
|
+
|
14
|
+
#
|
15
|
+
# Get a variables in this binding
|
16
|
+
#
|
17
|
+
def [](key)
|
18
|
+
eval(key.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Set a variable in this binding
|
23
|
+
#
|
24
|
+
def []=(key, val)
|
25
|
+
Thread.current[:_alter_binding_local_] = val
|
26
|
+
eval("#{key} = Thread.current[:_alter_binding_local_]")
|
27
|
+
Thread.current[:_alter_binding_local_] = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Return all the local variables in the binding
|
32
|
+
#
|
33
|
+
def local_variables
|
34
|
+
eval("local_variables")
|
35
|
+
end
|
36
|
+
alias_method :keys, :local_variables
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
class Proc
|
43
|
+
|
44
|
+
#
|
45
|
+
# Chain two procs together, returning a new proc. Each proc is executed one after the other,
|
46
|
+
# with the same input arguments. The return value is an array of all the procs' return values.
|
47
|
+
#
|
48
|
+
# You can use either the .join method, or the overloaded & operator.
|
49
|
+
#
|
50
|
+
# Examples:
|
51
|
+
# joined = proc1 & proc2
|
52
|
+
# joined = proc1.join proc2
|
53
|
+
# newproc = proc { 1 } & proc { 2 }
|
54
|
+
# newproc.call #=> [1, 2]
|
55
|
+
#
|
56
|
+
def join(other=nil, &block)
|
57
|
+
other ||= block
|
58
|
+
proc { |*args| [self.call(*args), other.call(*args)] }
|
59
|
+
end
|
60
|
+
alias_method :&, :join
|
61
|
+
|
62
|
+
#
|
63
|
+
# Chains two procs together, returning a new proc. The output from each proc is passed into
|
64
|
+
# the input of the next one.
|
65
|
+
#
|
66
|
+
# Example:
|
67
|
+
# chain = proc { 1 } | proc { |input| input + 1 }
|
68
|
+
# chain.call #=> 2
|
69
|
+
#
|
70
|
+
def chain(other=nil, &block)
|
71
|
+
other ||= block
|
72
|
+
proc { |*args| other.call( self.call(*args) ) }
|
73
|
+
end
|
74
|
+
alias_method :|, :chain
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
unless defined?(BasicObject)
|
81
|
+
#
|
82
|
+
# Backported BasicObject for Ruby 1.8
|
83
|
+
#
|
84
|
+
class BasicObject
|
85
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
class Object
|
92
|
+
|
93
|
+
#
|
94
|
+
# Negates a boolean, chained-method style.
|
95
|
+
#
|
96
|
+
# Example:
|
97
|
+
# >> 10.even?
|
98
|
+
# => true
|
99
|
+
# >> 10.not.even?
|
100
|
+
# => false
|
101
|
+
#
|
102
|
+
def not
|
103
|
+
NotWrapper.new(self)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
class NotWrapper < BasicObject # :nodoc:
|
109
|
+
def initialize(orig)
|
110
|
+
@orig = orig
|
111
|
+
end
|
112
|
+
|
113
|
+
def inspect
|
114
|
+
"{NOT #{@orig.inspect}}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def is_a?(other)
|
118
|
+
other === self
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(meth, *args, &block)
|
122
|
+
result = @orig.send(meth, *args, &block)
|
123
|
+
if result.is_a? ::TrueClass or result.is_a? ::FalseClass
|
124
|
+
!result
|
125
|
+
else
|
126
|
+
raise "Sorry, I don't know how to invert #{result.inspect}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
unless IO.respond_to? :copy_stream
|
134
|
+
|
135
|
+
class IO
|
136
|
+
|
137
|
+
#
|
138
|
+
# IO.copy_stream backport
|
139
|
+
#
|
140
|
+
def self.copy_stream(input, output)
|
141
|
+
while chunk = input.read(8192)
|
142
|
+
output.write(chunk)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
class Range
|
153
|
+
|
154
|
+
#
|
155
|
+
# Pick a random number from the range.
|
156
|
+
#
|
157
|
+
def rand
|
158
|
+
Kernel.rand(self)
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
class Struct
|
166
|
+
|
167
|
+
#
|
168
|
+
# Transform this struct into a JSON hash
|
169
|
+
#
|
170
|
+
def to_hash
|
171
|
+
hash = {}
|
172
|
+
each_pair { |k,v| hash[k] = v }
|
173
|
+
hash
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Transform the struct into a simple JSON hash.
|
178
|
+
#
|
179
|
+
def to_json(*args)
|
180
|
+
to_hash.to_json
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
module URI
|
188
|
+
|
189
|
+
#
|
190
|
+
# Return a Hash of the variables in the query string
|
191
|
+
#
|
192
|
+
def params
|
193
|
+
query.to_params
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
|
200
|
+
class Time
|
201
|
+
|
202
|
+
#
|
203
|
+
# Which "quarter" of the year does this date fall into?
|
204
|
+
#
|
205
|
+
def quarter
|
206
|
+
(month / 3.0).ceil
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
#
|
214
|
+
# Give ObjectSpace Enumerable powers (select, map, etc.)
|
215
|
+
#
|
216
|
+
module ObjectSpace
|
217
|
+
|
218
|
+
include Enumerable
|
219
|
+
|
220
|
+
alias_method :each, :each_object
|
221
|
+
|
222
|
+
extend self
|
223
|
+
|
224
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Alias "Enumerator" to "Enum"
|
2
|
+
if RUBY_VERSION["1.8"]
|
3
|
+
require 'enumerator'
|
4
|
+
Enumerator = Enumerable::Enumerator unless defined? Enumerator
|
5
|
+
end
|
6
|
+
|
7
|
+
unless defined? Enum
|
8
|
+
if defined? Enumerator
|
9
|
+
Enum = Enumerator
|
10
|
+
else
|
11
|
+
$stderr.puts "WARNING: Couldn't find the Enumerator class. Enum will not be available."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RbConfig = Config unless defined? RbConfig
|
16
|
+
|
17
|
+
|
18
|
+
class Object
|
19
|
+
|
20
|
+
unless defined?(__DIR__)
|
21
|
+
#
|
22
|
+
# This method is convenience for the `File.expand_path(File.dirname(__FILE__))` idiom.
|
23
|
+
# (taken from Michael Fellinger's Ramaze... thanx, dood! :D)
|
24
|
+
#
|
25
|
+
def __DIR__(*args)
|
26
|
+
filename = caller[0][/^(.*):/, 1]
|
27
|
+
dir = File.expand_path(File.dirname(filename))
|
28
|
+
::File.expand_path(::File.join(dir, *args.map{|a| a.to_s}))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# 'autoreq' is a replacement for autoload that can load gems.
|
34
|
+
#
|
35
|
+
# Usage:
|
36
|
+
# autoreq :Constant, 'thing-to-require'
|
37
|
+
# autoreq :Constant, 'thing-to-require'
|
38
|
+
# autoreq :OtherConstant do
|
39
|
+
# gem 'somegem', '~> 1.2'
|
40
|
+
# require 'somegem'
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
def autoreq(const, path=nil, &block)
|
44
|
+
raise "Error: autoreq must be supplied with a file to load, or a block." unless !!path ^ block_given?
|
45
|
+
|
46
|
+
if block_given?
|
47
|
+
Module.autoreqs[const] = block
|
48
|
+
else
|
49
|
+
Module.autoreqs[const] = path
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Remove an object, method, constant, etc.
|
55
|
+
#
|
56
|
+
def del(x)
|
57
|
+
case x
|
58
|
+
when String
|
59
|
+
del(x.to_sym)
|
60
|
+
when Class, Module
|
61
|
+
Object.send(:remove_const, x.name)
|
62
|
+
when Method
|
63
|
+
x.owner.send(:undef_method, x.name)
|
64
|
+
when Symbol
|
65
|
+
if Object.const_get(x)
|
66
|
+
Object.send(:remove_const, x)
|
67
|
+
elsif method(x)
|
68
|
+
undef_method x
|
69
|
+
end
|
70
|
+
else
|
71
|
+
raise "Error: don't know how to 'del #{x.inspect}'"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# The hidden singleton lurks behind everyone
|
76
|
+
def metaclass
|
77
|
+
class << self
|
78
|
+
self
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def meta_eval &blk
|
83
|
+
metaclass.instance_eval &blk
|
84
|
+
end
|
85
|
+
|
86
|
+
# Adds methods to a metaclass
|
87
|
+
def meta_def name, &blk
|
88
|
+
meta_eval { define_method name, &blk }
|
89
|
+
end
|
90
|
+
|
91
|
+
# Defines an instance method within a class
|
92
|
+
def class_def name, &blk
|
93
|
+
class_eval { define_method name, &blk }
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Slightly gross hack to add a class method.
|
98
|
+
#
|
99
|
+
def self.alias_class_method(dest, src)
|
100
|
+
metaclass.send(:alias_method, dest, src)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Patch 'Module#const_missing' to support 'autoreq' (which can autoload gems)
|
107
|
+
#
|
108
|
+
class Module
|
109
|
+
|
110
|
+
@@autoreq_is_searching_for = nil
|
111
|
+
|
112
|
+
alias const_missing_without_autoreq const_missing
|
113
|
+
|
114
|
+
def const_missing(const)
|
115
|
+
return if const == @@autoreq_is_searching_for
|
116
|
+
|
117
|
+
if thing = autoreqs[const]
|
118
|
+
case thing
|
119
|
+
when String, Symbol
|
120
|
+
require thing
|
121
|
+
when Proc
|
122
|
+
Object.class_eval(&thing)
|
123
|
+
else
|
124
|
+
raise "Error: Don't know how to autoload a #{thing.class}: #{thing.inspect}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
@@autoreq_is_searching_for = const
|
129
|
+
const_get(const) || const_missing_without_autoreq(const)
|
130
|
+
end
|
131
|
+
|
132
|
+
def autoreqs
|
133
|
+
@@autoreqs ||= {}
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
####################################################################
|
140
|
+
|
141
|
+
require 'epitools/autoloads'
|
142
|
+
|
143
|
+
####################################################################
|
data/lib/epitools/path.rb
CHANGED
@@ -5,7 +5,9 @@
|
|
5
5
|
# tmp bugs
|
6
6
|
#
|
7
7
|
|
8
|
-
require 'epitools'
|
8
|
+
require 'epitools/minimal'
|
9
|
+
require 'epitools/core_ext/enumerable'
|
10
|
+
require 'epitools/core_ext/string'
|
9
11
|
|
10
12
|
#
|
11
13
|
# Path: An object-oriented wrapper for files. (Combines useful methods from FileUtils, File, Dir, and more!)
|
data/lib/epitools/sys.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
#
|
2
|
+
# Like a Stuct, but automatically casts input to specific types.
|
2
3
|
#
|
4
|
+
# Example:
|
5
|
+
#
|
6
|
+
# class SomeRecord < TypedStruct["some_id:int amount:float x:string a,b,c:bool"]; end
|
7
|
+
# record = SomeRecord.new(69, 12348.871, "stringy", true, 1, "no")
|
3
8
|
#
|
4
9
|
class TypedStruct < Struct
|
5
10
|
|
@@ -11,11 +16,12 @@ class TypedStruct < Struct
|
|
11
16
|
# A perhaps-too-clever table of { "typename" => convert_proc } mappings.
|
12
17
|
#
|
13
18
|
CONVERTERS = Hash[ *{
|
14
|
-
|
15
|
-
["
|
16
|
-
["
|
17
|
-
["
|
18
|
-
["
|
19
|
+
["str", "string"] => :passthru,
|
20
|
+
["int", "integer"] => proc { |me| me.to_i },
|
21
|
+
["hex"] => proc { |me| me.to_i(16) },
|
22
|
+
["date", "time", "datetime"] => proc { |me| DateTime.parse me },
|
23
|
+
["timestamp"] => proc { |me| Time.at me },
|
24
|
+
["bool", "boolean"] => proc do |me|
|
19
25
|
case me
|
20
26
|
when false, 0, "0", "off", "no", "false", nil
|
21
27
|
false
|
@@ -24,10 +30,7 @@ class TypedStruct < Struct
|
|
24
30
|
else
|
25
31
|
raise "Invalid boolean type: #{me.inspect}"
|
26
32
|
end
|
27
|
-
|
28
|
-
["date", "time", "datetime"] => proc { |me| DateTime.parse me },
|
29
|
-
["timestamp"] => proc { |me| Time.at me },
|
30
|
-
|
33
|
+
end
|
31
34
|
}.map { |names, converter| names.map { |n| [n, converter] } }.flatten ]
|
32
35
|
|
33
36
|
#
|
data/lib/epitools/wm.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'epitools/path'
|
2
|
+
require 'epitools/typed_struct'
|
3
|
+
|
1
4
|
module WM
|
2
5
|
|
3
6
|
raise "Error: wmctrl not found." unless Path.which("wmctrl")
|
@@ -332,8 +335,10 @@ module WM
|
|
332
335
|
specials = $1.split("-")
|
333
336
|
key = specials.pop
|
334
337
|
|
338
|
+
key.downcase! if key =~ /^[A-Z]$/
|
339
|
+
|
335
340
|
specials.each do |special|
|
336
|
-
if special =~ /^(Ctrl|Shift|Alt)$/
|
341
|
+
if special =~ /^(Ctrl|Shift|Alt)$/i
|
337
342
|
mods << $1
|
338
343
|
else
|
339
344
|
raise "Error: unknown modifier #{special}"
|
@@ -363,8 +368,12 @@ module WM
|
|
363
368
|
|
364
369
|
temp.write eventstring
|
365
370
|
temp.flush
|
371
|
+
temp.seek 0
|
372
|
+
p [:temp, temp.read]
|
366
373
|
|
367
|
-
|
374
|
+
cmd = "xse", "-window", window_id, "-file", temp.path
|
375
|
+
p [:cmd, cmd]
|
376
|
+
unless system(*cmd)
|
368
377
|
raise "Error: couldn't send key commands to 'xse'. (Is xsendevents installed?)"
|
369
378
|
end
|
370
379
|
end
|
data/spec/autoreq_spec.rb
CHANGED
data/spec/path_spec.rb
CHANGED
@@ -288,7 +288,7 @@ describe Path do
|
|
288
288
|
Path.which("ruby").should_not be_nil
|
289
289
|
Path.which("asdfasdfhkajlsdhfkljashdf").should be_nil
|
290
290
|
Path.which("ruby").class.should == Path
|
291
|
-
Path.which("
|
291
|
+
Path.which("cat", "ls", "rm").should == ["/bin/cat", "/bin/ls", "/bin/rm"]
|
292
292
|
end
|
293
293
|
|
294
294
|
it "Path[]s another path" do
|
data/spec/wm_spec.rb
CHANGED
@@ -11,9 +11,16 @@ describe WM do
|
|
11
11
|
WM.current_desktop.nil? == false
|
12
12
|
end
|
13
13
|
|
14
|
+
def to_events(keys)
|
15
|
+
WM::Window.new.keys_to_events(keys)
|
16
|
+
end
|
17
|
+
|
14
18
|
it "parses X keys-string" do
|
15
|
-
events =
|
16
|
-
events.should == ["<
|
19
|
+
events = to_events "Hello<Ctrl-T><Ctrl-L><Return>!!!"
|
20
|
+
events.should == ["Shift<Key>H", "<Key>e", "<Key>l", "<Key>l", "<Key>o", "Ctrl<Key>t", "Ctrl<Key>l", "<Key>Return", "Shift<Key>0x21", "Shift<Key>0x21", "Shift<Key>0x21"]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "handles something weird" do
|
17
24
|
end
|
18
25
|
|
19
26
|
it "sends keys to this window" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epitools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- lib/epitools/core_ext/array.rb
|
88
88
|
- lib/epitools/core_ext/enumerable.rb
|
89
89
|
- lib/epitools/core_ext/hash.rb
|
90
|
+
- lib/epitools/core_ext/misc.rb
|
90
91
|
- lib/epitools/core_ext/numbers.rb
|
91
92
|
- lib/epitools/core_ext/object.rb
|
92
93
|
- lib/epitools/core_ext/string.rb
|
@@ -98,6 +99,7 @@ files:
|
|
98
99
|
- lib/epitools/lcs.rb
|
99
100
|
- lib/epitools/mimemagic.rb
|
100
101
|
- lib/epitools/mimemagic_tables.rb
|
102
|
+
- lib/epitools/minimal.rb
|
101
103
|
- lib/epitools/niceprint.rb
|
102
104
|
- lib/epitools/numwords.rb
|
103
105
|
- lib/epitools/path.rb
|