rmtools 1.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.
@@ -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
+
@@ -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