rmtools 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +15 -0
- data/Manifest.txt +37 -0
- data/README.txt +10 -0
- data/Rakefile +39 -0
- data/ext/extconf.rb +12 -0
- data/ext/rmtools.cpp +529 -0
- data/ext/rmtools.h +161 -0
- data/lib/rmtools.rb +53 -0
- data/lib/rmtools/arguments.rb +24 -0
- data/lib/rmtools/array.rb +189 -0
- data/lib/rmtools/binding.rb +23 -0
- data/lib/rmtools/boolean.rb +57 -0
- data/lib/rmtools/coloring.rb +82 -0
- data/lib/rmtools/cyr-time.rb +49 -0
- data/lib/rmtools/cyrilic.rb +124 -0
- data/lib/rmtools/dumps.rb +192 -0
- data/lib/rmtools/enum.rb +90 -0
- data/lib/rmtools/hash.rb +40 -0
- data/lib/rmtools/io.rb +303 -0
- data/lib/rmtools/js.rb +25 -0
- data/lib/rmtools/limited_string.rb +17 -0
- data/lib/rmtools/logging.rb +158 -0
- data/lib/rmtools/module.rb +113 -0
- data/lib/rmtools/numeric.rb +82 -0
- data/lib/rmtools/object.rb +74 -0
- data/lib/rmtools/printing.rb +41 -0
- data/lib/rmtools/proc.rb +25 -0
- data/lib/rmtools/random.rb +195 -0
- data/lib/rmtools/range.rb +100 -0
- data/lib/rmtools/setup.rb +21 -0
- data/lib/rmtools/string.rb +276 -0
- data/lib/rmtools/string_to_proc.rb +113 -0
- data/lib/rmtools/stringscanner.rb +58 -0
- data/lib/rmtools/time.rb +32 -0
- data/lib/rmtools/traceback.rb +106 -0
- data/lib/rmtools/tree.rb +71 -0
- metadata +191 -0
data/lib/rmtools/enum.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Enumerable
|
3
|
+
|
4
|
+
def import(arr, index)
|
5
|
+
self[index] = arr[index]
|
6
|
+
end
|
7
|
+
|
8
|
+
def export(arr, index)
|
9
|
+
arr[index] = self[index]
|
10
|
+
end
|
11
|
+
|
12
|
+
def foldl(o, m=nil)
|
13
|
+
block_given? ?
|
14
|
+
reduce(m ? yield(m) : nil) {|m, i| m ? m.send(o, yield(i)) : yield(i)} :
|
15
|
+
reduce(m) {|m, i| m ? m.send(o, i) : i}
|
16
|
+
end
|
17
|
+
|
18
|
+
def foldr(o, m=nil)
|
19
|
+
block_given? ?
|
20
|
+
reverse.reduce(m ? yield(m) : nil) {|m, i| m ? yield(i).send(o, m) : yield(i)} :
|
21
|
+
reverse.reduce(m) {|m, i| m ? i.send(o, m) : i}
|
22
|
+
end
|
23
|
+
|
24
|
+
if RUBY_VERSION < "1.8.7"
|
25
|
+
def xprod(obj, inverse=false)
|
26
|
+
size = self.size
|
27
|
+
if obj.kinda Array or obj.is Set
|
28
|
+
objsize = obj.size
|
29
|
+
raise ArgumentError, "can't complement #{self.class} with void container" if objsize == 0
|
30
|
+
if size == 1
|
31
|
+
case objsize
|
32
|
+
when 1 then inverse ? [[obj.first, first]] : [[first, obj.first]]
|
33
|
+
else obj.xprod_one first, !inverse
|
34
|
+
end
|
35
|
+
else
|
36
|
+
case objsize
|
37
|
+
when 1 then xprod_one obj.first, inverse
|
38
|
+
else xprod_many obj, inverse
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else xprod_one obj, inverse
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def xprod_one(obj, inverse)
|
47
|
+
inverse ? map {|te| [obj, te]} : map {|te| [te, obj]}
|
48
|
+
end
|
49
|
+
|
50
|
+
def xprod_many(obj, inverse)
|
51
|
+
a = []
|
52
|
+
inverse ?
|
53
|
+
obj.each {|oe| each {|te| a << [oe, te]}} :
|
54
|
+
each {|te| obj.each {|oe| a << [te, oe]}}
|
55
|
+
a
|
56
|
+
end
|
57
|
+
else
|
58
|
+
def xprod(obj, inverse=false)
|
59
|
+
obj = obj.to_a if obj.is Set
|
60
|
+
obj = [obj] if !obj.kinda(Array)
|
61
|
+
inverse ? obj.to_a.product(self) : product(obj)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
module ObjectSpace
|
68
|
+
extend Enumerable
|
69
|
+
|
70
|
+
def self.each(&b) self.each_object(&b) end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class Object
|
75
|
+
|
76
|
+
# block must return a pair
|
77
|
+
def unfold(break_if=lambda{|x|x==0}, &splitter)
|
78
|
+
obj, container = self, []
|
79
|
+
until begin
|
80
|
+
result = splitter[obj]
|
81
|
+
container.unshift result[1]
|
82
|
+
break_if[result[0]]
|
83
|
+
end
|
84
|
+
obj = result[0]
|
85
|
+
end
|
86
|
+
container
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
data/lib/rmtools/hash.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def +(other_hash)
|
5
|
+
merge(other_hash || {})
|
6
|
+
end
|
7
|
+
|
8
|
+
def concat(other_hash)
|
9
|
+
merge!(other_hash || {})
|
10
|
+
end
|
11
|
+
|
12
|
+
def unify_strs
|
13
|
+
each {|k, v|
|
14
|
+
if k.is String
|
15
|
+
sk = k.to_sym
|
16
|
+
self[sk] = v if !self[sk]
|
17
|
+
elsif k.is Symbol
|
18
|
+
sk = k.to_s
|
19
|
+
self[sk] = v if !self[sk]
|
20
|
+
end
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def max; [(m = keys.max), self[m]] end
|
25
|
+
|
26
|
+
def min; [(m = keys.min), self[m]] end
|
27
|
+
|
28
|
+
# should be overriden by extension maps
|
29
|
+
def map2
|
30
|
+
h = {}
|
31
|
+
each {|k, v| h[k] = yield(k,v)}
|
32
|
+
h
|
33
|
+
end
|
34
|
+
|
35
|
+
def map!
|
36
|
+
each {|k, v| self[k] = yield(k,v)}
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/rmtools/io.rb
ADDED
@@ -0,0 +1,303 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Dir
|
3
|
+
|
4
|
+
def include?(name)
|
5
|
+
#content.map {|f| File.split(f)[1]}.include? name
|
6
|
+
entries.include? name
|
7
|
+
end
|
8
|
+
|
9
|
+
def recursive_content(flat=true)
|
10
|
+
list = []
|
11
|
+
cont = content.map {|f|
|
12
|
+
if File.directory?(f)
|
13
|
+
rc = Dir.new(f).recursive_content.map {|f| f.sub(/^\.\//, '')}
|
14
|
+
flat ? list.concat(rc) : rc
|
15
|
+
else flat ? (list << f) : f
|
16
|
+
end
|
17
|
+
}
|
18
|
+
(flat ? list : cont)
|
19
|
+
end
|
20
|
+
|
21
|
+
def content
|
22
|
+
Dir["#{path}/**"].b || to_a[2..-1].sort.map {|c| File.join path, c}
|
23
|
+
end
|
24
|
+
|
25
|
+
def parent
|
26
|
+
newpath = File.dirname(path)
|
27
|
+
Dir.new(newpath) if newpath != path
|
28
|
+
end
|
29
|
+
|
30
|
+
def child(idx)
|
31
|
+
df = content[idx]
|
32
|
+
if File.file?(df)
|
33
|
+
File.new(df)
|
34
|
+
elsif File.directory?(df)
|
35
|
+
Dir.new(df)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def children
|
40
|
+
content.map {|df|
|
41
|
+
if File.file?(df)
|
42
|
+
File.new(df)
|
43
|
+
elsif File.directory?(df)
|
44
|
+
Dir.new(df)
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def refresh
|
50
|
+
return if !File.directory?(path)
|
51
|
+
Dir.new(path)
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
displaypath = case path
|
56
|
+
when /^(\/|\w:)/ then path
|
57
|
+
when /^\./ then File.join(Dir.pwd, path[1..-1])
|
58
|
+
else File.join(Dir.pwd, path)
|
59
|
+
end
|
60
|
+
"<#Dir \"#{displaypath}\" #{to_a.size - 2} elements>"
|
61
|
+
end
|
62
|
+
|
63
|
+
def name
|
64
|
+
File.basename(path)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Fixing windoze path problems
|
68
|
+
# requires amatch gem for better performance
|
69
|
+
def real_name
|
70
|
+
n, p, count = name, parent, []
|
71
|
+
return n if !p
|
72
|
+
pp, pc, sc = parent.path, parent.to_a[2..-1], to_a
|
73
|
+
if defined? Amatch
|
74
|
+
ms = pc.sizes.max
|
75
|
+
count = [:hamming_similar, :levenshtein_similar, :jaro_similar].sum {|m| pc.group_by {|_| _.upcase.ljust(ms).send(m, n)}.max[1]}.count.to_a
|
76
|
+
max = count.lasts.max
|
77
|
+
res = count.find {|c|
|
78
|
+
c[1] == max and File.directory?(df=File.join(pp, c[0])) and Dir.new(df).to_a == sc
|
79
|
+
}
|
80
|
+
return res[0] if res
|
81
|
+
end
|
82
|
+
(pc - count).find {|c|
|
83
|
+
File.directory?(df=File.join(pp, c)) and Dir.new(df).to_a == sc
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
class File
|
90
|
+
|
91
|
+
def inspect
|
92
|
+
"<#File \"#{path}\" #{closed? ? 'closed' : stat.size.bytes}>"
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.include?(name, str)
|
96
|
+
f = new name, 'r'
|
97
|
+
incl = f.include? str
|
98
|
+
f.close
|
99
|
+
incl
|
100
|
+
end
|
101
|
+
|
102
|
+
def include?(str)
|
103
|
+
while s = gets do return true if s.include? str end
|
104
|
+
end
|
105
|
+
|
106
|
+
def parent
|
107
|
+
newpath = File.dirname(path)
|
108
|
+
Dir.new(newpath) if newpath != path
|
109
|
+
end
|
110
|
+
|
111
|
+
def name
|
112
|
+
File.basename(path)
|
113
|
+
end
|
114
|
+
|
115
|
+
def ext
|
116
|
+
name[/[^.]+$/]
|
117
|
+
end
|
118
|
+
|
119
|
+
def refresh
|
120
|
+
return if !File.file?(path)
|
121
|
+
close
|
122
|
+
File.new(path,'r')
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.modify(file, bak=true)
|
126
|
+
orig_text = read file
|
127
|
+
text = yield orig_text
|
128
|
+
rename file, file+'.bak' if bak
|
129
|
+
RMTools.rw(file, text.is(String) ? text : orig_text)
|
130
|
+
end
|
131
|
+
|
132
|
+
def cp(df)
|
133
|
+
dir = File.dirname df
|
134
|
+
FileUtils.mkpath dir unless File.directory? dir
|
135
|
+
FileUtils.cp path, df
|
136
|
+
end
|
137
|
+
|
138
|
+
def mv(df)
|
139
|
+
dir = File.dirname df
|
140
|
+
FileUtils.mkpath dir unless File.directory? dir
|
141
|
+
rename df
|
142
|
+
end
|
143
|
+
|
144
|
+
# Fixing windoze path problems
|
145
|
+
# requires amatch gem for better performance
|
146
|
+
def real_name
|
147
|
+
n, p, count = name, parent, []
|
148
|
+
pp, pc, ss = parent.path, parent.to_a[2..-1], stat
|
149
|
+
ms = pc.sizes.max
|
150
|
+
n, ext = n.rsplit('.', 2)
|
151
|
+
if ext
|
152
|
+
re = /\.#{ext}$/i
|
153
|
+
pc.reject! {|f| !f[re]}
|
154
|
+
end
|
155
|
+
if defined? Amatch
|
156
|
+
count = [:hamming_similar, :levenshtein_similar, :jaro_similar].sum {|m| pc.group_by {|f| (ext ? f[0..-(ext.size+2)] : f).upcase.ljust(ms).send(m, n)}.max[1]}.count.to_a
|
157
|
+
max = count.lasts.max
|
158
|
+
res = count.find {|c|
|
159
|
+
c[1] == max and File.file?(df=File.join(pp, c[0])) and File.stat(df) == ss
|
160
|
+
}
|
161
|
+
return res[0] if res
|
162
|
+
end
|
163
|
+
(pc - count).find {|c|
|
164
|
+
File.file?(df=File.join(pp, c)) and File.stat(df) == ss
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
PathMemo = {} if !defined? PathMemo
|
169
|
+
def self.real_path path, memo=1
|
170
|
+
a = expand_path(path).split(/[\/\\]/)
|
171
|
+
a.each_index {|i|
|
172
|
+
if a[j=-(i+1)]['~']
|
173
|
+
n = i+2>a.size ? a[j] : join(a[0..-(i+2)], a[j])
|
174
|
+
a[j] = PathMemo[n] || real_name(n)
|
175
|
+
PathMemo[n] = a[j] if memo
|
176
|
+
else break
|
177
|
+
end
|
178
|
+
}
|
179
|
+
a*'/'
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.real_name(df)
|
183
|
+
if file?(df)
|
184
|
+
new(df).real_name
|
185
|
+
elsif directory?(df)
|
186
|
+
Dir.new(df).real_name
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
class IO
|
193
|
+
|
194
|
+
def gets2
|
195
|
+
str = ''
|
196
|
+
str << (c = read 1) until c and "\r\n\b".include? c or eof?
|
197
|
+
str
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
module RMTools
|
203
|
+
|
204
|
+
def tick!
|
205
|
+
print %W{|\b /\b -\b \\\b +\b X\b}.rand
|
206
|
+
end
|
207
|
+
|
208
|
+
def executing? file
|
209
|
+
caller(0)[0] =~ /^#{file}:/
|
210
|
+
end
|
211
|
+
|
212
|
+
def rw(df, value=nil)
|
213
|
+
return false if value.nil?
|
214
|
+
df.gsub!('\\', '/')
|
215
|
+
path = File.dirname(df)
|
216
|
+
FileUtils.mkpath(path) if !File.directory?(path)
|
217
|
+
mode = RUBY_VERSION > '1.9' ? :wb : 'wb'
|
218
|
+
File.open(df, mode) {|f| f << value}
|
219
|
+
value.size
|
220
|
+
end
|
221
|
+
|
222
|
+
def write(df, value='', pos=0)
|
223
|
+
return false if value.nil?
|
224
|
+
df.gsub!('\\', '/')
|
225
|
+
path = File.dirname(df)
|
226
|
+
FileUtils.mkpath(path) if !File.directory?(path)
|
227
|
+
if pos == 0
|
228
|
+
mode = RUBY_VERSION > '1.9' ? :ab : 'ab'
|
229
|
+
File.open(df, mode) {|f| f << value}
|
230
|
+
else
|
231
|
+
if pos < 0
|
232
|
+
raise IndexError, "file #{df} does not exist, can't write from position #{pos}" if !File.file?(df)
|
233
|
+
raise IndexError, "file #{df} is shorter than #{(-pos).bytes}, can't write from position #{pos}" if (size = File.size(df)) < -pos
|
234
|
+
pos = size + pos
|
235
|
+
end
|
236
|
+
File.open(df, 'r+') {|f| f.pos = pos; f << value}
|
237
|
+
end
|
238
|
+
value.size
|
239
|
+
end
|
240
|
+
|
241
|
+
def read(df, mode='rb')
|
242
|
+
df.gsub!('\\', '/')
|
243
|
+
if !File.file?(df)
|
244
|
+
$log.debug "#{df} is missed!"
|
245
|
+
else
|
246
|
+
File.open(df, mode) {|f| f.read}
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def read_lines(df, *lines)
|
251
|
+
return if !lines or lines.empty?
|
252
|
+
str = ""
|
253
|
+
last = lines.max
|
254
|
+
if !File.file?(df)
|
255
|
+
puts "#{df} is missed!"
|
256
|
+
else
|
257
|
+
File.open(df, 'r') {|f|
|
258
|
+
f.each {|line|
|
259
|
+
no = f.lineno
|
260
|
+
str << line if no.in lines
|
261
|
+
break if no == last
|
262
|
+
}}
|
263
|
+
str
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def highlighted_line(file, line)
|
268
|
+
if defined? SCRIPT_LINES__
|
269
|
+
" >> #{Painter.green SCRIPT_LINES__[file][line.to_i - 1].chop}" if SCRIPT_LINES__[file]
|
270
|
+
else
|
271
|
+
file = Readline::TEMPLOG if file == '(irb)' and defined? Readline::TEMPLOG
|
272
|
+
" >> #{Painter.green read_lines(file, line.to_i).chop}" if File.file? file
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def tail(file, bytes=1000)
|
277
|
+
if !File.file?(file)
|
278
|
+
puts "#{file} is missed!"
|
279
|
+
else
|
280
|
+
IO.read(file, bytes, File.size(file)-bytes)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def tail_n(file, qty=10)
|
285
|
+
if !File.file?(file)
|
286
|
+
return puts "#{file} is missed!"
|
287
|
+
end
|
288
|
+
size = File.size(file)
|
289
|
+
lines = []
|
290
|
+
strlen = 0
|
291
|
+
step = qty*100
|
292
|
+
while qty > 0 and (offset = size-strlen-step) >= 0 and (str = IO.read(file, step, offset)).b
|
293
|
+
i = str.index("\n") || str.size
|
294
|
+
strlen += step - i
|
295
|
+
new_lines = str[i+1..-1]/"\n"
|
296
|
+
qty -= new_lines.size
|
297
|
+
lines = new_lines.concat(lines)
|
298
|
+
end
|
299
|
+
lines[-qty..-1]
|
300
|
+
end
|
301
|
+
|
302
|
+
module_function :tick!, :executing?, :rw, :write, :read, :read_lines, :highlighted_line, :tail, :tail_n
|
303
|
+
end
|
data/lib/rmtools/js.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def method_missing(met, *args)
|
5
|
+
str = met.id2name
|
6
|
+
if str[/=$/]
|
7
|
+
self[str[0..-2]] = args[0]
|
8
|
+
else
|
9
|
+
raise NoMethodError, "undefined method `#{str}' for #{self}:#{(self.class)}" if !args.empty?
|
10
|
+
a = self[str]
|
11
|
+
(a == default) ? self[met] : a
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class String
|
18
|
+
if !method_defined? :plus
|
19
|
+
alias :plus :+ end
|
20
|
+
|
21
|
+
def +(str)
|
22
|
+
plus str.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|