rmtools 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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