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.
- 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
@@ -0,0 +1,41 @@
|
|
1
|
+
module RMTools
|
2
|
+
|
3
|
+
class TempPrinter
|
4
|
+
__init__
|
5
|
+
|
6
|
+
def initialize object=nil, format=nil
|
7
|
+
if @object = object
|
8
|
+
@format = '"' + format.gsub(/:([a-z_]\w*)/, '#{@\1.inspect}') + '"'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def format_str
|
13
|
+
@object.instance_eval @format
|
14
|
+
end
|
15
|
+
|
16
|
+
def p(str=format_str)
|
17
|
+
STDOUT << @eraser if @eraser
|
18
|
+
cols = ENV['COLUMNS'].to_i
|
19
|
+
astr = RUBY_VERSION < '1.9' ? UTF2ANSI[str] : str
|
20
|
+
rows = astr.split("\n").sum {|line| 1 + line.size/cols}
|
21
|
+
eraser = "\b" + "\r\b"*rows + " "
|
22
|
+
@eraser = eraser + " "*cols*rows + eraser
|
23
|
+
puts str
|
24
|
+
end
|
25
|
+
|
26
|
+
def end
|
27
|
+
@eraser = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def clear
|
31
|
+
p ""
|
32
|
+
end
|
33
|
+
|
34
|
+
def end!
|
35
|
+
clear
|
36
|
+
self.end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/lib/rmtools/proc.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Proc
|
3
|
+
include RMTools
|
4
|
+
NULL = lambda {} unless defined? Proc::NULL
|
5
|
+
attr_accessor :string
|
6
|
+
|
7
|
+
def inspect
|
8
|
+
"#{str=to_s}: #{@string ? Painter.green(@string) : "\n"+highlighted_line(*str.match(/([^@]+):(\d+)>$/)[1..2])}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.when condition
|
12
|
+
if condition.is String
|
13
|
+
sleep 0.001 until eval condition
|
14
|
+
else
|
15
|
+
sleep 0.001 until condition.call
|
16
|
+
end
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.eval string, binding=nil
|
21
|
+
(proc = (binding || Kernel).eval "lambda {#{string}}").string = string
|
22
|
+
proc
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module RMTools
|
3
|
+
begin
|
4
|
+
require 'securerandom'
|
5
|
+
SecureRandom.random_bytes
|
6
|
+
Urandom = true
|
7
|
+
rescue
|
8
|
+
Urandom = false
|
9
|
+
end
|
10
|
+
Numbers = '0123456789'
|
11
|
+
Chars = 'abcdefghijklmnopqrstuvwxyz'
|
12
|
+
Alphanum = Chars + Chars.upcase + Numbers
|
13
|
+
ASCII_readable = '!"#$%&\'()*+,-./[\]^_`{|}~:;<=>?@ ' + Alphanum
|
14
|
+
RuChars = UTF2ANSI[RU_LETTERS[0]]
|
15
|
+
RuAlphanum = UTF2ANSI[RU_LETTERS.join] + Numbers
|
16
|
+
|
17
|
+
def randstr(len=8, what=:alphanum)
|
18
|
+
s = ''
|
19
|
+
res = case what
|
20
|
+
when :bytes, :binary
|
21
|
+
if Urandom
|
22
|
+
SecureRandom.random_bytes len
|
23
|
+
else
|
24
|
+
len.times {s.concat rand 256}; s
|
25
|
+
end
|
26
|
+
when :ascii
|
27
|
+
if Urandom
|
28
|
+
SecureRandom.random_bytes(len*3).tr("^ -~", '')[0...len]
|
29
|
+
else
|
30
|
+
len.times {s.concat ASCII_readable[rand 95].ord}; s
|
31
|
+
end
|
32
|
+
when :char
|
33
|
+
if Urandom
|
34
|
+
res = SecureRandom.base64(len*2).tr("^a-z", '')[0...len]
|
35
|
+
else
|
36
|
+
len.times {s.concat Chars[rand 26].ord}; s
|
37
|
+
end
|
38
|
+
when :alphanum
|
39
|
+
if Urandom
|
40
|
+
res = SecureRandom.base64(len).tr("+/=", '')[0...len]
|
41
|
+
else
|
42
|
+
len.times {s.concat Alphanum[rand 62].ord}; s
|
43
|
+
end
|
44
|
+
when :num, :digit
|
45
|
+
if Urandom
|
46
|
+
res = SecureRandom.hex(len).tr("^0-9", '')[0...len]
|
47
|
+
else
|
48
|
+
len.times {s.concat Numbers[rand 10].ord}; s
|
49
|
+
end
|
50
|
+
when :hex
|
51
|
+
if Urandom
|
52
|
+
res = SecureRandom.hex len/2
|
53
|
+
else
|
54
|
+
len.times {s.concat Numbers[rand 10].ord}; s
|
55
|
+
end
|
56
|
+
when :cyr, :cyrilic
|
57
|
+
if Urandom
|
58
|
+
res = ANSI2UTF[SecureRandom.random_bytes(len*8).tr("^\270\340-\377", '')[0...len]]
|
59
|
+
else
|
60
|
+
len.times {s.concat RuChars[rand 33].ord}; ANSI2UTF[s]
|
61
|
+
end
|
62
|
+
when :cyr_full, :cyr_alphanum
|
63
|
+
if Urandom
|
64
|
+
res = ANSI2UTF[SecureRandom.random_bytes(len*3.5).tr("^0-9\250\270\340-\377\300-\337", '')[0...len]]
|
65
|
+
else
|
66
|
+
len.times {s.concat RuAlphanum[rand 76].ord}; ANSI2UTF[s]
|
67
|
+
end
|
68
|
+
|
69
|
+
when Symbol then raise ArgumentError, "invalid symbol :#{what}, valid symbols are
|
70
|
+
:bytes, :binary, :char, :alphanum, :num, :digit, :hex, :cyr, :cyrilic, :cyr_full, :cyr_alphanum"
|
71
|
+
when String then res = randstr(len*10, :bytes).tr("^#{what}", '')
|
72
|
+
else raise ArgumentError, "invalid argument #{what}, class #{(what.class)}"
|
73
|
+
end
|
74
|
+
res << randstr((len-res.size)*2, what) while res.size < len
|
75
|
+
res[0...len]
|
76
|
+
end
|
77
|
+
|
78
|
+
if RUBY_VERSION >= "1.8.7"
|
79
|
+
def randarr(len, &b)
|
80
|
+
a = (0...len).to_a.shuffle
|
81
|
+
block_given? ? a.map!(&b) : a
|
82
|
+
end
|
83
|
+
else
|
84
|
+
def randarr(len, &b)
|
85
|
+
d = (0...len).to_a
|
86
|
+
a = Array.new(len) {d.rand!}
|
87
|
+
block_given? ? a.map!(&b) : a
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module_function :randstr, :randarr
|
92
|
+
end
|
93
|
+
|
94
|
+
module Enumerable
|
95
|
+
|
96
|
+
def randsample(qty=Kernel.rand(size))
|
97
|
+
a, b = [], to_a.dup
|
98
|
+
qty.times {a << b.rand!}
|
99
|
+
a
|
100
|
+
end
|
101
|
+
|
102
|
+
def rand(&cond)
|
103
|
+
if cond
|
104
|
+
a, b, s = Set.new, to_a, size
|
105
|
+
loop {
|
106
|
+
i = Kernel.rand s
|
107
|
+
if i.in a
|
108
|
+
return if a.size == s
|
109
|
+
elsif !cond[e = b[i]]
|
110
|
+
a << i
|
111
|
+
else return e
|
112
|
+
end
|
113
|
+
}
|
114
|
+
else to_a[Kernel.rand(size)]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
class Range
|
121
|
+
|
122
|
+
def rand
|
123
|
+
self.begin + Kernel.rand(size)
|
124
|
+
end
|
125
|
+
|
126
|
+
def randseg
|
127
|
+
(a = rand) > (b = rand) ? b..a : a..b
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
class Array
|
133
|
+
|
134
|
+
def self.rand(len)
|
135
|
+
RMTools.randarr(len)
|
136
|
+
end
|
137
|
+
|
138
|
+
def rand(&cond)
|
139
|
+
if cond
|
140
|
+
a, s = [], size
|
141
|
+
loop {
|
142
|
+
i = Kernel.rand s
|
143
|
+
if i.in a
|
144
|
+
return if a.size == s
|
145
|
+
elsif !cond[e = self[i]]
|
146
|
+
a << i
|
147
|
+
else return e
|
148
|
+
end
|
149
|
+
}
|
150
|
+
else self[Kernel.rand(size)]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def rand!
|
155
|
+
delete_at Kernel.rand size
|
156
|
+
end
|
157
|
+
|
158
|
+
def randdiv(int)
|
159
|
+
len = 2*int.to_i+1
|
160
|
+
return [self] if len <= 1
|
161
|
+
newarr = []
|
162
|
+
arr = dup
|
163
|
+
while arr.size > 0
|
164
|
+
lenn = Kernel.rand(len)
|
165
|
+
next if lenn < 1
|
166
|
+
newarr << arr.slice!(0, lenn)
|
167
|
+
end
|
168
|
+
newarr
|
169
|
+
end
|
170
|
+
|
171
|
+
def randdiv!(int)
|
172
|
+
len = 2*int.to_i+1
|
173
|
+
return [self] if len <= 1
|
174
|
+
newarr = []
|
175
|
+
while size > 0
|
176
|
+
lenn = Kernel.rand(len)
|
177
|
+
next if lenn < 1
|
178
|
+
newarr << slice!(0, lenn)
|
179
|
+
end
|
180
|
+
newarr
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
class String
|
186
|
+
|
187
|
+
def self.rand(*args)
|
188
|
+
RMTools.randstr(*args)
|
189
|
+
end
|
190
|
+
|
191
|
+
def rand(chsize=1)
|
192
|
+
self[Kernel.rand(size*chsize), chsize]
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Range
|
3
|
+
|
4
|
+
def &(range)
|
5
|
+
return range&self if range.is XRange
|
6
|
+
beg = [self.begin, range.begin].max
|
7
|
+
end_ = [self.include_end.end, range.include_end.end].min
|
8
|
+
beg > end_ ? nil : beg..end_
|
9
|
+
end
|
10
|
+
|
11
|
+
def |(range)
|
12
|
+
return range|self if range.is XRange
|
13
|
+
range = range.include_end
|
14
|
+
self_ = self.include_end
|
15
|
+
return XRange.new self, range if !x?(range)
|
16
|
+
[self.begin, range.begin].min..[self_.end, range.end].max
|
17
|
+
end
|
18
|
+
|
19
|
+
def x?(range)
|
20
|
+
range_end = range.include_end.end
|
21
|
+
self_end = self.include_end.end
|
22
|
+
if self_end < range_end
|
23
|
+
self_end >= range.begin - (self_end.kinda Integer and range.begin.kinda Integer).to_i
|
24
|
+
else
|
25
|
+
range_end >= self.begin - (self.begin.kinda Integer and range_end.kinda Integer).to_i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def <=>(range) (self.begin <=> range.begin).b || self.include_end.end <=> range.include_end.end end
|
30
|
+
|
31
|
+
def include_end() exclude_end? ? self.begin..(self.end - 1) : self end
|
32
|
+
|
33
|
+
def center() (first + last + (!exclude_end?).to_i)/2 end
|
34
|
+
|
35
|
+
def part(i, j) first+(i-1)*size/j...first+i*size/j unless i < 1 or j < 1 or j < i end
|
36
|
+
|
37
|
+
def size() last - first + (!exclude_end?).to_i end
|
38
|
+
|
39
|
+
def /(i) first...size/i end
|
40
|
+
|
41
|
+
def from(ary) ary[self] end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class XRange
|
46
|
+
attr_accessor :ranges
|
47
|
+
__init__
|
48
|
+
|
49
|
+
def initialize *args
|
50
|
+
if (str = args[0]).is String
|
51
|
+
str.scan(/([&|])?((-?\d+)\.\.(\.)?(-?\d+))/).each {|s|
|
52
|
+
s[2], s[4] = s[2].to_i, s[4].to_i
|
53
|
+
r = s[3] ? s[2]...s[4] : s[2]..s[4]
|
54
|
+
@ranges = case s[0]
|
55
|
+
when '&', '^'; intersect r
|
56
|
+
when '|', 'v'; union r
|
57
|
+
else [r]
|
58
|
+
end
|
59
|
+
}
|
60
|
+
@ranges.sort!
|
61
|
+
else
|
62
|
+
0.upto(args.sort!.size-2) {|i| args[i,2] = [nil, args[i]|args[i+1]] if args[i].x? args[i+1]}
|
63
|
+
@ranges = args.compact
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def &(range)
|
68
|
+
if range.is Range
|
69
|
+
XRange.new *intersect(range)
|
70
|
+
else
|
71
|
+
@ranges.map {|r| range & r}.foldl(:|)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def |(range)
|
76
|
+
if range.is Range
|
77
|
+
XRange.new *union(range)
|
78
|
+
else
|
79
|
+
@ranges.each {|r| range |= r}
|
80
|
+
range
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def intersect(range)
|
85
|
+
@ranges.map {|r| r&range}.compact
|
86
|
+
end
|
87
|
+
|
88
|
+
def union(range)
|
89
|
+
changed = (rs = @ranges.map {|r| (r.x?range) ? r|range : r}) != @ranges
|
90
|
+
changed ? rs : rs << range
|
91
|
+
end
|
92
|
+
|
93
|
+
include Enumerable
|
94
|
+
|
95
|
+
def each(&b) @ranges.each {|r| r.each &b} end
|
96
|
+
|
97
|
+
def from(ary) @ranges.foldl(:+) {|r| ary[r]} end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
Dir.chdir(File.expand_path File.dirname __FILE__) {require 'io'; require 'boolean'}
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
def ext_files_not_modified(ext_name='rmtools')
|
6
|
+
return unless name = Gem.source_index.gems.keys.find {|n|
|
7
|
+
n =~ /^#{ext_name}-\d/
|
8
|
+
}
|
9
|
+
gemspec = Gem.source_index.gems[name]
|
10
|
+
full_path = gemspec.full_gem_path
|
11
|
+
ext_files = gemspec.files.grep(/^ext\//)
|
12
|
+
ext_files.each {|f|
|
13
|
+
insalled = File.join(full_path, f)
|
14
|
+
return unless File.file? insalled and Digest::SHA256.file(f) == Digest::SHA256.file(insalled)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def compile_manifest(exc=['pkg'])
|
19
|
+
fs = Dir.new('.').recursive_content
|
20
|
+
RMTools.rw 'Manifest.txt', (exc ? fs.reject {|i| i[/^(#{exc*'|'})\//]} : fs)*"\n"
|
21
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class String
|
3
|
+
if !method_defined? :/
|
4
|
+
alias :/ :split
|
5
|
+
end
|
6
|
+
|
7
|
+
def inline
|
8
|
+
count("\n") == 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(str)
|
12
|
+
concat str.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
# %{blah blah
|
16
|
+
# wall of text in the interpreter
|
17
|
+
# oh shi~ may be we should
|
18
|
+
# save this into variable
|
19
|
+
# } >> (str='')
|
20
|
+
# ok, easily saved to variable
|
21
|
+
def >>(str)
|
22
|
+
str.replace(self + str)
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_with_offsets text, offset
|
26
|
+
index = index(text)
|
27
|
+
start = [0, index - offset].max
|
28
|
+
_end = index + text.size
|
29
|
+
[self[start...index], text, self[_end, offset]]
|
30
|
+
end
|
31
|
+
|
32
|
+
def div(dvsr, includesplitter=1, reportheaders=nil)
|
33
|
+
return lendiv dvsr if dvsr.kinda Fixnum
|
34
|
+
a = split(dvsr)
|
35
|
+
return a if !includesplitter and !reportheaders
|
36
|
+
skan = nil
|
37
|
+
case dvsr
|
38
|
+
when String
|
39
|
+
a = (1...a.size).map {|i| dvsr+a[i]}.unshift a[0] if includesplitter
|
40
|
+
when Regexp
|
41
|
+
skan = scan(dvsr).unshift ''
|
42
|
+
a = (0...a.size).map {|i| skan[i].to_s+a[i]} if includesplitter
|
43
|
+
end
|
44
|
+
(reportheaders and skan) ? [a, skan] : a
|
45
|
+
end
|
46
|
+
|
47
|
+
def rdiv(dvsr, includesplitter=1, reportheaders=nil)
|
48
|
+
return lendiv dvsr if dvsr.kinda Fixnum
|
49
|
+
a = split(dvsr)
|
50
|
+
return a if !includesplitter and !reportheaders
|
51
|
+
skan = nil
|
52
|
+
case dvsr
|
53
|
+
when String
|
54
|
+
a = (0...a.size).map {|i| a[i]+dvsr} if includesplitter
|
55
|
+
when Regexp
|
56
|
+
skan = scan(dvsr)
|
57
|
+
a = (0...a.size).map {|i| a[i]+skan[i]} if includesplitter
|
58
|
+
end
|
59
|
+
(reportheaders and skan) ? [a, skan] : a
|
60
|
+
end
|
61
|
+
|
62
|
+
def lendiv(len)
|
63
|
+
return [self] if len <= 0
|
64
|
+
str = dup
|
65
|
+
arr = []
|
66
|
+
while str.b
|
67
|
+
arr << str.slice!(0, len)
|
68
|
+
end
|
69
|
+
arr
|
70
|
+
end
|
71
|
+
|
72
|
+
def split_to_lines(maxlen, charsize=nil, no_blanks=false, strips=true)
|
73
|
+
raise Exception, "Can't break text with maxlen = #{maxlen}" if maxlen < 1
|
74
|
+
a = split("\n")
|
75
|
+
charsize ||= a[0].cyr? ? 2 : 1
|
76
|
+
a.map {|string| string.strip.split_to_blocks(maxlen*charsize, nil, false, no_blanks, strips)}.flatten*"\n"
|
77
|
+
end
|
78
|
+
|
79
|
+
def split_to_blocks(maxlen, terminator=nil, strict_overhead=true, no_blanks=true, strips=false)
|
80
|
+
raise Exception, "Can't break text with maxlen = #{maxlen}" if maxlen < 1
|
81
|
+
blocks = []
|
82
|
+
term_re = /[^#{terminator}]+\z/ if terminator and terminator != :syntax
|
83
|
+
return [self] if size <= maxlen
|
84
|
+
words, buf = split(strips ? ' ' : / /), nil
|
85
|
+
while words.b or buf.b
|
86
|
+
if terminator and blocks.b and (buf_add = if terminator == :syntax
|
87
|
+
blocks[-1].split_by_syntax maxlen, buf.size
|
88
|
+
else blocks[-1][term_re]
|
89
|
+
end.b)
|
90
|
+
if buf_add == blocks[-1]
|
91
|
+
blocks.pop
|
92
|
+
else blocks[-1] = blocks[-1][0...-buf_add.size]
|
93
|
+
end
|
94
|
+
buf = buf_add + buf
|
95
|
+
end
|
96
|
+
blocks << ''
|
97
|
+
if buf
|
98
|
+
blocks[-1] << buf
|
99
|
+
buf = nil
|
100
|
+
end
|
101
|
+
while words.b
|
102
|
+
buf = words.shift + ' '
|
103
|
+
break if blocks[-1].size + buf.size - 1 > maxlen
|
104
|
+
blocks[-1] << buf
|
105
|
+
buf = nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
blocks.reject! &:empty? if no_blanks
|
109
|
+
blocks.strips! if strips
|
110
|
+
blocks.each {|b| raise Exception, "can't split string by #{terminator} to blocks with max length = #{maxlen}" if b.size > maxlen} if strict_overhead
|
111
|
+
blocks
|
112
|
+
end
|
113
|
+
|
114
|
+
RMTools::URL_RE = %r{^((?:([^:]+)://)#{ # ( protocol
|
115
|
+
}([^/:]*(?::(\d+))?))?#{ # root[:port] )
|
116
|
+
}((/[^?#]*?(?:\.(\w+))?)#{ # ( path[.fileext]
|
117
|
+
}(?:\?(.*?))?)?#{ # [?query params] )
|
118
|
+
}(?:#(.+))?#{ # [ #anchor ]
|
119
|
+
}$} unless defined? RMTools::URL_RE
|
120
|
+
def parseuri
|
121
|
+
m = match RMTools::URL_RE
|
122
|
+
!m || m[0].empty? ?
|
123
|
+
{ 'href' => self } :
|
124
|
+
{ 'href' => self,
|
125
|
+
'root' => m[1],
|
126
|
+
'protocol' => m[2],
|
127
|
+
'host' => m[3],
|
128
|
+
'port' => m[4] ? m[4].to_i : 80,
|
129
|
+
'fullpath' => m[5] || '/',
|
130
|
+
'pathname' => m[5] || '/',
|
131
|
+
'path' => m[6] || '',
|
132
|
+
'ext' => m[7],
|
133
|
+
'query' => m[8] && m[8].to_hash(false),
|
134
|
+
'anchor' => m[9] }
|
135
|
+
end
|
136
|
+
|
137
|
+
def utf(from_encoding)
|
138
|
+
Iconv.new('UTF-8', from_encoding).iconv(self)
|
139
|
+
end
|
140
|
+
|
141
|
+
def utf!(from_encoding)
|
142
|
+
replace utf from_encoding
|
143
|
+
end
|
144
|
+
|
145
|
+
def bytes
|
146
|
+
arr = []
|
147
|
+
each_byte {|b| arr << "\\x#{b.hex}"}
|
148
|
+
arr
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_re(esc=false)
|
152
|
+
Regexp.new(esc ? Regexp.escape(self) : self)
|
153
|
+
end
|
154
|
+
|
155
|
+
def lchomp(match)
|
156
|
+
if index(match) == 0
|
157
|
+
self[match.size..-1]
|
158
|
+
else
|
159
|
+
self.dup
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def lchomp!(match)
|
164
|
+
if index(match) == 0
|
165
|
+
self[0...match.size] = ''
|
166
|
+
self
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def rsplit(splitter=$/, qty=0)
|
171
|
+
reverse.split(splitter, qty).reverse.reverses
|
172
|
+
end
|
173
|
+
|
174
|
+
def until(splitter=$/)
|
175
|
+
split(splitter, 2)[0]
|
176
|
+
end
|
177
|
+
alias :till :until
|
178
|
+
|
179
|
+
def after(splitter=$/)
|
180
|
+
split(splitter, 2)[1]
|
181
|
+
end
|
182
|
+
|
183
|
+
def bump_version(splt='.')
|
184
|
+
re = /(?:(\d*)#{Regexp.escape splt})?/
|
185
|
+
s = File.split self
|
186
|
+
s[0] == '.' ?
|
187
|
+
s[1].reverse.sub(re) {$1?"#{$1.to_i+1}#{splt}":"1#{splt}"}.reverse :
|
188
|
+
File.join(s[0], s[1].reverse.sub(re) {$1?"#{$1.to_i+1}#{splt}":"1#{splt}"}.reverse)
|
189
|
+
end
|
190
|
+
alias :next_version :bump_version
|
191
|
+
|
192
|
+
def bump!(splt='.')
|
193
|
+
replace bump_version splt
|
194
|
+
end
|
195
|
+
|
196
|
+
if RUBY_VERSION < "1.9"
|
197
|
+
def ord; self[0] end
|
198
|
+
else
|
199
|
+
# BUGFIX?
|
200
|
+
alias :sub19 :sub
|
201
|
+
alias :sub19! :sub!
|
202
|
+
alias :gsub19 :gsub
|
203
|
+
alias :gsub19! :gsub!
|
204
|
+
|
205
|
+
def sub! a,b=nil,&c
|
206
|
+
if b
|
207
|
+
if b=~/\\\d/
|
208
|
+
b = b.sub19!(/\\\d/) {|m| "\#{$#{m[1,1]}}"}
|
209
|
+
sub19!(a) {eval "\"#{b}\""}
|
210
|
+
else sub19!(a) {b} end
|
211
|
+
else sub19! a,&c end
|
212
|
+
end
|
213
|
+
|
214
|
+
def sub a,b=nil,&c
|
215
|
+
if b
|
216
|
+
if b=~/\\\d/
|
217
|
+
b = b.sub19(/\\\d/) {|m| "\#{$#{m[1,1]}}"}
|
218
|
+
sub19(a) {eval "\"#{b}\""}
|
219
|
+
else sub19(a) {b} end
|
220
|
+
else sub19 a,&c end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def to_limited len=100
|
225
|
+
LimitedString.new self, len
|
226
|
+
end
|
227
|
+
|
228
|
+
protected
|
229
|
+
def split_by_syntax(maxlen, buflen=0)
|
230
|
+
len, add = maxlen - buflen, nil
|
231
|
+
[/[^.?!]+\z/, /[^;]+\z/, /[^\n]+/, /\S+\z/, /[^。]+z/, /[^、]+z/].each {|t|
|
232
|
+
if !(add = self[t]) or add.size <= len
|
233
|
+
return add
|
234
|
+
end
|
235
|
+
}
|
236
|
+
add
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
class Indent < String
|
242
|
+
attr_reader :indent
|
243
|
+
|
244
|
+
def initialize(indent=' ')
|
245
|
+
@indent = indent
|
246
|
+
super ''
|
247
|
+
end
|
248
|
+
|
249
|
+
def +@
|
250
|
+
self << @indent
|
251
|
+
end
|
252
|
+
|
253
|
+
def -@
|
254
|
+
self.chomp! @indent
|
255
|
+
end
|
256
|
+
|
257
|
+
def i(&block)
|
258
|
+
+self
|
259
|
+
res = yield
|
260
|
+
-self
|
261
|
+
res
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
class Regexp
|
267
|
+
|
268
|
+
def | re
|
269
|
+
Regexp.new(source+'|'+re.source, options | re.options)
|
270
|
+
end
|
271
|
+
|
272
|
+
def in string
|
273
|
+
string =~ self
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|