rmtools 1.2.0 → 1.2.2b
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +3 -2
- data/README.txt +1 -1
- data/Rakefile +1 -1
- data/ext/rmtools.cpp +5 -3
- data/lib/rmtools.rb +1 -1
- data/lib/rmtools/core/arguments.rb +1 -1
- data/lib/rmtools/core/class.rb +1 -1
- data/lib/rmtools/core/kernel.rb +6 -3
- data/lib/rmtools/core/object.rb +21 -0
- data/lib/rmtools/core/threadify.rb +17 -0
- data/lib/rmtools/db/active_record.rb +27 -0
- data/lib/rmtools/dev/code_reading.rb +556 -0
- data/lib/rmtools/dev/logging.rb +6 -5
- data/lib/rmtools/dev/trace_format.rb +8 -1
- data/lib/rmtools/dev/traceback.rb +2 -1
- data/lib/rmtools/enumerable/array.rb +4 -0
- data/lib/rmtools/enumerable/array_iterators.rb +14 -3
- data/lib/rmtools/enumerable/common.rb +4 -0
- data/lib/rmtools/enumerable/range.rb +9 -1
- data/lib/rmtools/fs/dir.rb +4 -0
- data/lib/rmtools/fs/file.rb +3 -1
- data/lib/rmtools/fs/io.rb +33 -7
- data/lib/rmtools/{load.rb → init.rb} +0 -0
- data/lib/rmtools/rand/array.rb +17 -0
- data/lib/rmtools/rand/enum.rb +2 -2
- data/lib/rmtools/text/string_scanner.rb +6 -4
- data/lib/rmtools/text/string_split.rb +6 -6
- data/lib/rmtools/xml/finders.rb +21 -12
- data/lib/rmtools/xml/string.rb +7 -2
- data/lib/rmtools_dev.rb +1 -1
- metadata +15 -11
- data/lib/rmtools/dev/code_reader.rb +0 -431
data/lib/rmtools/dev/logging.rb
CHANGED
@@ -32,7 +32,8 @@ module RMTools
|
|
32
32
|
|
33
33
|
def _set_format file, format
|
34
34
|
file.print = !format.q
|
35
|
-
file.out = format.out
|
35
|
+
file.out = format.out || format.log_file
|
36
|
+
file.color_out = format.color_out || format.color_log
|
36
37
|
|
37
38
|
file.path_format = '%'.in file.out if file.out
|
38
39
|
file.tf = format.time.to_a
|
@@ -95,7 +96,7 @@ module RMTools
|
|
95
96
|
if caler
|
96
97
|
str.sub! "%caller", caler.sub(String::CALLER_RE, cfg.cf)
|
97
98
|
end
|
98
|
-
log_str = @c.clean str
|
99
|
+
log_str = @c.clean str if !cfg.color_out
|
99
100
|
RMTools.write out, log_str if log_
|
100
101
|
Kernel.print str if print_
|
101
102
|
end
|
@@ -156,9 +157,9 @@ module RMTools
|
|
156
157
|
end
|
157
158
|
end
|
158
159
|
|
159
|
-
alias
|
160
|
-
alias
|
161
|
-
alias
|
160
|
+
alias :<= :debug
|
161
|
+
alias :<< :info
|
162
|
+
alias :< :warn
|
162
163
|
|
163
164
|
Modes.each {|m| define_method("#{m}=") {|mute| send :"mute_#{m}=", !mute}}
|
164
165
|
|
@@ -19,12 +19,19 @@ module RMTools
|
|
19
19
|
# >> 10/0 end
|
20
20
|
# from (irb):3
|
21
21
|
# >> divbyzero
|
22
|
+
|
23
|
+
IgnoreFiles = %r{#{Regexp.escape $:.grep(%r{/ruby/1\.(8|9\.\d)$})[0]}/irb(/|\.rb$)|/active_support/dependencies.rb$}
|
24
|
+
|
22
25
|
def format_trace(a)
|
23
26
|
bt, calls, i = [], [], 0
|
24
27
|
m = a[0].parse:caller
|
28
|
+
m.line -= 1 if m.file =~ /\.haml$/
|
25
29
|
while i < a.size
|
26
30
|
m2 = a[i+1] && a[i+1].parse(:caller)
|
27
|
-
|
31
|
+
m2.line -= 1 if m2 and m2.file =~ /\.haml$/
|
32
|
+
if m.path =~ IgnoreFiles
|
33
|
+
nil
|
34
|
+
elsif m and m.func and m2 and [m.path, m.line] == [m2.path, m2.line]
|
28
35
|
calls << " -> `#{m.func}'"
|
29
36
|
elsif m and m.line != 0 and line = RMTools.highlighted_line(m.path, m.line)
|
30
37
|
bt << "#{a[i]}#{calls.join}\n#{line}"
|
@@ -2,7 +2,7 @@
|
|
2
2
|
RMTools::require 'dev/trace_format'
|
3
3
|
require 'active_support/core_ext/class/attribute'
|
4
4
|
|
5
|
-
# 1.9 may hung up processing IO while generating traceback
|
5
|
+
# as for rmtools-1.1.0, 1.9 may hung up processing IO while generating traceback
|
6
6
|
if RUBY_VERSION < '1.9'
|
7
7
|
class Exception
|
8
8
|
alias :set_bt :set_backtrace
|
@@ -20,6 +20,7 @@ if RUBY_VERSION < '1.9'
|
|
20
20
|
# it will be possible to get the lines entered in IRB
|
21
21
|
# else it reads only ordinal require'd files
|
22
22
|
def set_backtrace src
|
23
|
+
message.hl! self.class
|
23
24
|
if format = self.class.__trace_format
|
24
25
|
src = RMTools.__send__ format, src
|
25
26
|
end
|
@@ -14,12 +14,14 @@ unless defined? RMTools::Iterators
|
|
14
14
|
# => [[1, 2, 3], [3, 4, 6]]
|
15
15
|
class Array
|
16
16
|
alias :throw_no :method_missing
|
17
|
-
RMTools::Iterators = %r{(#{(%w{select reject partition find_all find sum foldr
|
17
|
+
RMTools::Iterators = %r{^(#{(%w{every no select reject partition find_all find sum foldr}+instance_methods.grep(/_by$/))*'|'})_([\w\d\_]+[!?]?)}
|
18
18
|
|
19
19
|
def method_missing(method, *args, &block)
|
20
20
|
if match = (meth = method.to_s).match(RMTools::Iterators)
|
21
21
|
iterator, meth = match[1], match[2].to_sym
|
22
22
|
begin
|
23
|
+
iterator = :every? if iterator == :every
|
24
|
+
iterator = :no? if iterator == :no
|
23
25
|
return iterator == :sum ?
|
24
26
|
__send__(iterator, args.shift) {|i| i.__send__ meth, *args, &block}:
|
25
27
|
__send__(iterator) {|i| i.__send__ meth, *args, &block}
|
@@ -27,9 +29,18 @@ unless defined? RMTools::Iterators
|
|
27
29
|
e.message << " (`#{method}' interpreted as decorator-function `#{meth}')"
|
28
30
|
raise e
|
29
31
|
end
|
30
|
-
elsif meth.sub!(/sses([
|
32
|
+
elsif meth.sub!(/sses([=!?]?)$/, 'ss\1') or meth.sub!(/ies([=!?]?)$/, 'y\1') or meth.sub!(/s([=!?]?)$/, '\1')
|
33
|
+
assignment = meth =~ /=$/
|
31
34
|
meth = meth.to_sym
|
32
|
-
begin
|
35
|
+
begin
|
36
|
+
if assignment
|
37
|
+
if Array === args
|
38
|
+
each_with_index {|e,i| e.__send__ meth, args[i]}
|
39
|
+
else
|
40
|
+
each {|e| e.__send__ meth, args}
|
41
|
+
end
|
42
|
+
else map {|e| e.__send__ meth, *args, &block}
|
43
|
+
end
|
33
44
|
rescue NoMethodError => e
|
34
45
|
e.message << " (`#{method}' interpreted as map-function `#{meth}')"
|
35
46
|
raise e
|
@@ -192,13 +192,21 @@ public
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def empty?
|
195
|
-
@
|
195
|
+
@ranges.empty?
|
196
196
|
end
|
197
197
|
|
198
198
|
def include?(number_or_range)
|
199
199
|
@ranges.find_include?(number_or_range)
|
200
200
|
end
|
201
201
|
|
202
|
+
def begin
|
203
|
+
@ranges[0].begin
|
204
|
+
end
|
205
|
+
|
206
|
+
def end
|
207
|
+
@ranges[-1].end
|
208
|
+
end
|
209
|
+
|
202
210
|
def size
|
203
211
|
@ranges.sum_size
|
204
212
|
end
|
data/lib/rmtools/fs/dir.rb
CHANGED
data/lib/rmtools/fs/file.rb
CHANGED
data/lib/rmtools/fs/io.rb
CHANGED
@@ -43,13 +43,39 @@ module RMTools
|
|
43
43
|
value.size
|
44
44
|
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
# read('filename')
|
47
|
+
### => 'text from filename'
|
48
|
+
# read('nonexistent_filename')
|
49
|
+
# couldn't read from "nonexistent_filename" (called from (irb):9001)
|
50
|
+
### => nil
|
51
|
+
# read(['file1', 'file2', 'file3'])
|
52
|
+
### => 'text from first of file1, file2, file3 that exists'
|
53
|
+
# read(['file1', 'file2'], ['nonexistent_file1', 'nonexistent_file2'])
|
54
|
+
# coludn't read from neither "nonexistent_file1", nor "nonexistent_file2" (called from (irb):9003)
|
55
|
+
### => ['text from first of file1, file2 that exists', nil]
|
56
|
+
# read('file1', 'file2')
|
57
|
+
### => ['text from file1', 'text from file2]
|
58
|
+
# read('file1', ['file2', 'file3'])
|
59
|
+
### => ['text from file1', 'text from first of file2 and file3 that exists']
|
60
|
+
def read(*dests)
|
61
|
+
texts = dests.map {|dest|
|
62
|
+
dest = dest[0] if dest.size == 1
|
63
|
+
if dest.is Array
|
64
|
+
if file = dest.find {|f| File.file?(f.tr '\\', '/')}
|
65
|
+
File.open(file.tr('\\', '/'), File::RDONLY) {|f| f.read}
|
66
|
+
else
|
67
|
+
warn "couldn't read from neither #{dest[0].inspect} nor #{dest[1..-1].inspects*' nor '}; files missed (called from #{caller[0]})"
|
68
|
+
end
|
69
|
+
else
|
70
|
+
if File.file? dest.tr('\\', '/')
|
71
|
+
File.open(dest.tr('\\', '/'), File::RDONLY) {|f| f.read}
|
72
|
+
else
|
73
|
+
warn "couldn't read from #{dest.inspect}; file missed (called from #{caller[0]})"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
}
|
77
|
+
texts = texts[0] if texts.size == 1
|
78
|
+
texts
|
53
79
|
end
|
54
80
|
|
55
81
|
module_function :read, :write, :rw
|
File without changes
|
data/lib/rmtools/rand/array.rb
CHANGED
@@ -17,6 +17,23 @@ class Array
|
|
17
17
|
RMTools.randarr(len)
|
18
18
|
end
|
19
19
|
|
20
|
+
def rand
|
21
|
+
if block_given?
|
22
|
+
h, ua = {}, uniq
|
23
|
+
s = ua.size
|
24
|
+
loop {
|
25
|
+
i = Kernel.rand size
|
26
|
+
if h[i]
|
27
|
+
return if h.size == s
|
28
|
+
elsif yield(e = ua[i])
|
29
|
+
return e
|
30
|
+
else h[i] = true
|
31
|
+
end
|
32
|
+
}
|
33
|
+
else self[Kernel.rand(size)]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
20
37
|
def rand!
|
21
38
|
delete_at Kernel.rand size
|
22
39
|
end
|
data/lib/rmtools/rand/enum.rb
CHANGED
@@ -4,7 +4,7 @@ module Enumerable
|
|
4
4
|
def rand
|
5
5
|
if block_given?
|
6
6
|
h, ua = {}, to_a.uniq
|
7
|
-
|
7
|
+
s = ua.size
|
8
8
|
loop {
|
9
9
|
i = Kernel.rand size
|
10
10
|
if h[i]
|
@@ -20,7 +20,7 @@ module Enumerable
|
|
20
20
|
|
21
21
|
def randsample(qty=Kernel.rand(size))
|
22
22
|
a, b = [], to_a.dup
|
23
|
-
qty.times {a << b.rand!}
|
23
|
+
[qty, size].min.times {a << b.rand!}
|
24
24
|
a
|
25
25
|
end
|
26
26
|
|
@@ -22,7 +22,7 @@ class StringScanner
|
|
22
22
|
# node.sum {|n| n.__find(str, nslist).to_a} : node.__find(str, nslist)
|
23
23
|
# }
|
24
24
|
def each(re, cbs=nil, &cb)
|
25
|
-
@last =
|
25
|
+
@last = pos
|
26
26
|
res = scan_until re
|
27
27
|
if cbs
|
28
28
|
if cbs.is Hash
|
@@ -39,7 +39,7 @@ class StringScanner
|
|
39
39
|
end
|
40
40
|
else
|
41
41
|
while res
|
42
|
-
if cb = cbs.find {|
|
42
|
+
if cb = cbs.find {|patern, fun| pattern and matched[pattern]}
|
43
43
|
# patterns should be as explicit as possible
|
44
44
|
cb[1][self, $~] if cb[1]
|
45
45
|
@last = pos
|
@@ -61,10 +61,12 @@ class StringScanner
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def head
|
64
|
-
string[@last...pos-matched_size]
|
64
|
+
string[@last...pos-matched_size.to_i]
|
65
65
|
end
|
66
66
|
|
67
|
-
|
67
|
+
def tail
|
68
|
+
post_match || string[pos..-1]
|
69
|
+
end
|
68
70
|
|
69
71
|
def hl_next(re)
|
70
72
|
(res = scan_until re) && Painter.hl(string[[pos-1000, 0].max..pos+1000], res)
|
@@ -9,7 +9,7 @@ class String
|
|
9
9
|
def sharp_split(splitter, *args)
|
10
10
|
count, opts = args.fetch_opts [0, :flags], :include_splitter => true
|
11
11
|
if !opts[:report_headers] and opts[:include_splitter] and splitter.is Regexp
|
12
|
-
return split(/(?=#{splitter.source})
|
12
|
+
return split(/(?=#{splitter.source})/u, count)
|
13
13
|
end
|
14
14
|
a = split(splitter, count)
|
15
15
|
return a if !opts[:include_splitter] and !opts[:report_headers]
|
@@ -67,7 +67,7 @@ class String
|
|
67
67
|
add
|
68
68
|
end
|
69
69
|
|
70
|
-
def sanitize_blocks!(blocks, opts)
|
70
|
+
def sanitize_blocks!(blocks, maxlen, opts)
|
71
71
|
blocks.reject! {|b| b.empty?} if opts[:no_blanks]
|
72
72
|
blocks.strips! if opts[:strips]
|
73
73
|
blocks.each {|b| raise Exception, "can't split string by #{terminator} to blocks with max length = #{maxlen}" if b.size > maxlen} if opts[:strict_overhead]
|
@@ -97,7 +97,7 @@ class String
|
|
97
97
|
buf = buf_add + buf
|
98
98
|
end
|
99
99
|
if blocks.size == opts[:lines]
|
100
|
-
return sanitize_blocks! blocks, opts
|
100
|
+
return sanitize_blocks! blocks, maxlen, opts
|
101
101
|
end
|
102
102
|
blocks << ''
|
103
103
|
if buf
|
@@ -111,14 +111,14 @@ class String
|
|
111
111
|
buf = nil
|
112
112
|
end
|
113
113
|
end
|
114
|
-
sanitize_blocks! blocks, opts
|
114
|
+
sanitize_blocks! blocks, maxlen, opts
|
115
115
|
end
|
116
116
|
|
117
117
|
# 'An elegant way to factor duplication out of options passed to a series of method calls. Each method called in the block, with the block variable as the receiver, will have its options merged with the default options hash provided. '.cut_line 100
|
118
118
|
# => "An elegant way to factor duplication out of options passed to a series of method calls..."
|
119
119
|
def cut_line(maxlen, *opts)
|
120
120
|
terminator, opts = opts.fetch_opts [:syntax, :flags]
|
121
|
-
opts[:charsize] ||= RUBY_VERSION < '1.9' &&
|
121
|
+
opts[:charsize] ||= RUBY_VERSION < '1.9' && cyr? ? 2 : 1
|
122
122
|
return self if size <= maxlen
|
123
123
|
maxlen -= 3
|
124
124
|
split_to_blocks(maxlen*opts[:charsize], terminator, :strips => true, :strict_overhead => false, :lines => 1)[0][0, maxlen].chomp('.') + '...'
|
@@ -136,7 +136,7 @@ class String
|
|
136
136
|
# options: charsize, no_blanks, strips
|
137
137
|
def split_to_lines(maxlen, *opts)
|
138
138
|
raise Exception, "Can't break text with maxlen = #{maxlen}" if maxlen < 1
|
139
|
-
opts = opts.fetch_opts :flags, :strips=>true
|
139
|
+
opts = opts.fetch_opts [:flags], :strips=>true
|
140
140
|
a = split("\n")
|
141
141
|
opts[:charsize] ||= RUBY_VERSION < '1.9' && a[0].cyr? ? 2 : 1
|
142
142
|
a.map {|string| string.strip.split_to_blocks(maxlen*opts[:charsize], opts.merge(:strict_overhead => false))}.flatten*"\n"
|
data/lib/rmtools/xml/finders.rb
CHANGED
@@ -5,18 +5,27 @@ module LibXML::XML
|
|
5
5
|
DefaultNS = {}
|
6
6
|
|
7
7
|
FindByIndex = lambda {|node, ns, ss|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
index = ss.matched[1..-2]
|
9
|
+
if index.index('.')
|
10
|
+
range = Range(*index.split('..').to_is)
|
11
|
+
node = node.is(Array) ?
|
12
|
+
node.sum([]) {|n| n.__find(nil, ns, ss).to_a[range]} :
|
13
|
+
node.__find(nil, ns, ss).to_a[range]
|
14
|
+
else
|
15
|
+
node = node.is(Array) ?
|
16
|
+
node.map {|n| n.__find(nil, ns, ss)[index.to_i]}.compact :
|
17
|
+
node.__find(nil, ns, ss)[index.to_i]
|
18
|
+
end
|
19
|
+
node.is(Array) && node.size < 2 ? node[0] : node
|
12
20
|
}
|
21
|
+
|
13
22
|
FindByProc = lambda {|node, ns, ss|
|
14
23
|
str_to_eval = ss.matched[1..-2]
|
15
|
-
'_'
|
24
|
+
block = eval "lambda {|_| #{'_' if !str_to_eval['_']}#{str_to_eval}}"
|
16
25
|
node = node.is(Array) ?
|
17
|
-
node.sum {|n| n.__find(nil, ns, ss).select
|
18
|
-
node.__find(nil, ns, ss).select
|
19
|
-
node.is(Array) && node.size
|
26
|
+
node.sum([]) {|n| n.__find(nil, ns, ss).select(&block).to_a} :
|
27
|
+
node.__find(nil, ns, ss).select(&block)
|
28
|
+
node.is(Array) && node.size < 2 ? node[0] : node
|
20
29
|
}
|
21
30
|
|
22
31
|
class Node
|
@@ -31,7 +40,7 @@ module LibXML::XML
|
|
31
40
|
def find(xpath, nslist=DefaultNS)
|
32
41
|
node = self
|
33
42
|
ss = StringScanner.new xpath
|
34
|
-
ss.each %r{\[-?\d
|
43
|
+
ss.each %r{\[-?\d+(\.\.\d+)?\]|\{[^\}]+\}},
|
35
44
|
?[ => lambda {|ss|
|
36
45
|
if node; node = FindByIndex[node, nslist, ss]
|
37
46
|
else return [] end },
|
@@ -40,7 +49,7 @@ module LibXML::XML
|
|
40
49
|
else return [] end },
|
41
50
|
nil => lambda {|str|
|
42
51
|
node = node.is(Array) ?
|
43
|
-
node.sum {|n| n.__find(str, nslist).to_a} : node.__find(str, nslist)
|
52
|
+
node.sum([]) {|n| n.__find(str, nslist).to_a} : node.__find(str, nslist)
|
44
53
|
}
|
45
54
|
node ? (!ss.eos? || node.is(Array)) ? node : [node] : []
|
46
55
|
end
|
@@ -64,7 +73,7 @@ module LibXML::XML
|
|
64
73
|
xpath.sub!(/^([\w*])/, '//\1')
|
65
74
|
node = self
|
66
75
|
ss = StringScanner.new xpath
|
67
|
-
ss.each %r{\[-?\d
|
76
|
+
ss.each %r{\[-?\d+(\.\.\d+)?\]|\{[^\}]+\}},
|
68
77
|
?[ => lambda {|ss|
|
69
78
|
if node; node = FindByIndex[node, nslist, ss]
|
70
79
|
else return [] end },
|
@@ -73,7 +82,7 @@ module LibXML::XML
|
|
73
82
|
else return [] end },
|
74
83
|
nil => lambda {|str|
|
75
84
|
node = node.is(Array) ?
|
76
|
-
node.sum {|n| n.__find(str, nslist).to_a} : node.__find(str, nslist)
|
85
|
+
node.sum([]) {|n| n.__find(str, nslist).to_a} : node.__find(str, nslist)
|
77
86
|
}
|
78
87
|
node ? (!ss.eos? || node.is(Array)) ? node : [node] : []
|
79
88
|
end
|
data/lib/rmtools/xml/string.rb
CHANGED
@@ -25,10 +25,15 @@ class String
|
|
25
25
|
str = b || "<html/>"
|
26
26
|
doc = if forceutf
|
27
27
|
XML::HTMLParser.string(str.xml_to_utf, :options => 97,
|
28
|
-
|
28
|
+
:encoding => XML::Encoding::UTF_8).parse
|
29
29
|
else
|
30
30
|
begin
|
31
|
-
|
31
|
+
if RUBY_VERSION > '1.9'
|
32
|
+
XML::HTMLParser.string(str, :options => 97,
|
33
|
+
:encoding => XML::Encoding.const_get(__ENCODING__.to_s.tr('-','_').to_sym)).parse
|
34
|
+
else
|
35
|
+
XML::HTMLParser.string(str, :options => 97).parse
|
36
|
+
end
|
32
37
|
rescue
|
33
38
|
if enc = xml_charset
|
34
39
|
XML::HTMLParser.string(str, :options => 97,
|