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,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