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,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class LimitedString < String
|
3
|
+
attr_reader :len
|
4
|
+
__init__
|
5
|
+
|
6
|
+
def initialize str="", len=100
|
7
|
+
@len = len
|
8
|
+
super str
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
@len ||= 100
|
13
|
+
size > @len ? String.new(self[0...@len]+"…").inspect : super
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module RMTools
|
3
|
+
|
4
|
+
class RMLogger
|
5
|
+
__init__
|
6
|
+
attr_accessor :mute_info, :mute_warn, :mute_log, :mute_debug
|
7
|
+
|
8
|
+
RE = /^\(?(.*?([^\/\\]+?))\)?:(\d+)(?::in `([^']+)')?$/
|
9
|
+
Modes = %w{debug log info warn}.to_syms
|
10
|
+
NOPRINT = 4
|
11
|
+
NOLOG = 2
|
12
|
+
INLINE = 1
|
13
|
+
|
14
|
+
def initialize format={}
|
15
|
+
@clr = Coloring.new
|
16
|
+
@highlight = {
|
17
|
+
:warn => @clr.red_bold("WARN"),
|
18
|
+
:log => @clr.cyan("INFO"),
|
19
|
+
:info => @clr.cyan_bold("INFO"),
|
20
|
+
:debug => @clr.gray_bold("DEBUG")
|
21
|
+
}
|
22
|
+
@file_formats = Hash.new(@default_format = {})
|
23
|
+
set_format format, :global
|
24
|
+
end
|
25
|
+
|
26
|
+
def _set_format file, format
|
27
|
+
file.print = !format.q
|
28
|
+
file.out = format.out
|
29
|
+
|
30
|
+
file.path_format = '%'.in file.out if file.out
|
31
|
+
file.tf = (format.time || ["%H:%M:%S", "%03d"]).to_a
|
32
|
+
file.cf0 = format.caller || "#{@clr.gray('%f:%l')} #{@clr.red_bold(':%m')}"
|
33
|
+
file.cf = file.cf0.sub('%F'){'\1'}.sub('%f'){'\2'}.sub('%l'){'\3'}.sub('%m'){'\4'}
|
34
|
+
file.fmt = format.format || "%time %mode [%caller]: %text"
|
35
|
+
file._time, file._caller = '%time'.in(file.fmt), '%caller'.in(file.fmt)
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_format format={}, global=nil
|
39
|
+
if global
|
40
|
+
_set_format @default_format, format
|
41
|
+
else
|
42
|
+
_set_format(file_format={}, format)
|
43
|
+
@file_formats[File.expand_path(caller[0].till ':')] = file_format
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_format file=nil
|
48
|
+
cfg = @file_formats[file && File.expand_path(file)]
|
49
|
+
modes = Modes.reject {|m| send :"mute_#{m}"}
|
50
|
+
%{<Logger #{cfg.fmt.sub('%time', "%time(#{cfg.tf*'.'})").sub('%caller', "%caller(#{cfg.cf0})")}#{' -> '+cfg.out if cfg.out} #{modes.b ? modes.inspect : 'muted'}>}
|
51
|
+
end
|
52
|
+
|
53
|
+
def _print mode, text, opts, caler, bind, cfg
|
54
|
+
log_ = opts&NOLOG==0
|
55
|
+
print_ = opts&NOPRINT==0
|
56
|
+
str = cfg.fmt.dup
|
57
|
+
str.sub! "%mode", @highlight[mode]
|
58
|
+
if bind
|
59
|
+
text = text.reports bind
|
60
|
+
elsif !text.is(String)
|
61
|
+
text = text.inspect
|
62
|
+
end
|
63
|
+
str.sub! "%text", text
|
64
|
+
str << "\n" if opts&INLINE==0
|
65
|
+
out = cfg.out
|
66
|
+
if cfg._time or cfg.path_format
|
67
|
+
now = Time.now
|
68
|
+
if cfg._time
|
69
|
+
time = now.strftime cfg.tf[0]
|
70
|
+
time << ".#{cfg.tf[1]%[now.usec/1000]}" if cfg.tf[1]
|
71
|
+
str.sub! "%time", time
|
72
|
+
end
|
73
|
+
out = now.strftime cfg.out if cfg.path_format
|
74
|
+
end
|
75
|
+
str.sub! "%caller", caler.sub(RE, cfg.cf) if caler
|
76
|
+
log_str = @clr.clean str
|
77
|
+
RMTools.write out, log_str if log_
|
78
|
+
Kernel.print str if print_
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_binding a
|
82
|
+
a[0].is(Binding) ? [a[0], a[1] || 0] : [nil, a[0] || 0]
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_config!
|
86
|
+
@file_formats.empty? ? @default_format : @file_formats[File.expand_path(caller[1].till ':')]
|
87
|
+
end
|
88
|
+
|
89
|
+
# controllers:
|
90
|
+
# - $panic: print debug messages
|
91
|
+
# - $verbose: print log messages
|
92
|
+
# - $quiet: print only warn messages regardless of other globals
|
93
|
+
# - @mute_warn, @mute_info, @mute_log: do not print
|
94
|
+
# this messages regardless of any globals
|
95
|
+
# - @out_all: write to file any messages
|
96
|
+
|
97
|
+
def warn text=nil, *a
|
98
|
+
cfg = get_config!
|
99
|
+
if (cfg.out or cfg.print) && !@mute_warn
|
100
|
+
bind, opts = check_binding a
|
101
|
+
opts |= NOLOG if !cfg.out
|
102
|
+
opts |= NOPRINT if !cfg.print
|
103
|
+
text ||= yield if block_given?
|
104
|
+
_print(:warn, text, opts, cfg._caller && caller[0], bind, cfg)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def log text=nil, *a
|
109
|
+
cfg = get_config!
|
110
|
+
if (cfg.out or cfg.print && !$quiet && $verbose) && !@mute_log
|
111
|
+
bind, opts = check_binding a
|
112
|
+
opts |= NOLOG if !cfg.out
|
113
|
+
opts |= NOPRINT if !(cfg.print && !$quiet && $verbose)
|
114
|
+
text ||= yield if block_given?
|
115
|
+
_print(:log, text, opts, cfg._caller && caller[0], bind, cfg)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def info text=nil, *a
|
120
|
+
cfg = get_config!
|
121
|
+
if (cfg.print && !$quiet or cfg.out && cfg.out_all) && !@mute_info
|
122
|
+
bind, opts = check_binding a
|
123
|
+
opts |= NOLOG if !(cfg.out && cfg.out_all)
|
124
|
+
opts |= NOPRINT if !(cfg.print && !$quiet)
|
125
|
+
text ||= yield if block_given?
|
126
|
+
_print(:info, text, opts, cfg._caller && caller[0], bind, cfg)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def debug text=nil, *a
|
131
|
+
cfg = get_config!
|
132
|
+
if (cfg.print && $panic && !$quiet or cfg.out && cfg.out_all) && !@mute_debug
|
133
|
+
bind, opts = check_binding a
|
134
|
+
opts |= NOLOG if !(cfg.out && cfg.out_all)
|
135
|
+
opts |= NOPRINT if !(cfg.print && $panic && !$quiet)
|
136
|
+
text ||= yield if block_given?
|
137
|
+
_print(:debug, text, opts, cfg._caller && caller[0], bind, cfg)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
alias << info
|
142
|
+
alias < warn
|
143
|
+
|
144
|
+
Modes.each {|m| define_method("#{m}=") {|b| send :"mute_#{m}=", !b}}
|
145
|
+
|
146
|
+
def outall=(x) @default_format.out_all = x end
|
147
|
+
def print=(x) @default_format.print = x end
|
148
|
+
def out=(x) @default_format.out = x end
|
149
|
+
|
150
|
+
def out_all() @default_format.out_all end
|
151
|
+
def print() @default_format.print end
|
152
|
+
def out() @default_format.out end
|
153
|
+
|
154
|
+
def inspect() get_format end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Module # :nodoc:
|
3
|
+
|
4
|
+
def children
|
5
|
+
constants.map! {|c| module_eval c}.find_all {|c| c.kinda Module rescue()}
|
6
|
+
end
|
7
|
+
|
8
|
+
def each_child
|
9
|
+
constants.map! {|c| module_eval c}.each {|c| yield c if c.kinda Module}
|
10
|
+
constants
|
11
|
+
end
|
12
|
+
|
13
|
+
def self_name
|
14
|
+
@self_name ||= name.rsplit('::', 2)[1] || name
|
15
|
+
end
|
16
|
+
|
17
|
+
def my_methods filter=//
|
18
|
+
self.singleton_methods.sort!.grep(filter)
|
19
|
+
end
|
20
|
+
alias personal_methods my_methods
|
21
|
+
|
22
|
+
private
|
23
|
+
# example:
|
24
|
+
#
|
25
|
+
# def divide_ten_by x
|
26
|
+
# 10 / x
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# def maybe(*args)
|
30
|
+
# yield *args rescue(puts $!)
|
31
|
+
# end
|
32
|
+
# ...
|
33
|
+
#
|
34
|
+
# decorate :divide_ten_by, :maybe # =>
|
35
|
+
# def divide_ten_by x
|
36
|
+
# 10 / x rescue(puts $!)
|
37
|
+
# end
|
38
|
+
def decorate f1, f2
|
39
|
+
f1_clone = f1.to_s.dup
|
40
|
+
f1_clone.bump! '_' while method_defined? f1_clone.to_sym
|
41
|
+
class_eval do
|
42
|
+
alias :"#{f1_clone}" :"#{f1}"
|
43
|
+
define_method(f1) {|*args| send(f2, *args, &method(f1_clone))}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# some FP, example:
|
48
|
+
#
|
49
|
+
# def divide_ten_by x
|
50
|
+
# 10 / x
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# def maybe
|
54
|
+
# lambda {|*args| yield *args rescue(puts $!)}
|
55
|
+
# end
|
56
|
+
# ...
|
57
|
+
#
|
58
|
+
# decorated_fof :divide_ten_by, :maybe # =>
|
59
|
+
# def divide_ten_by
|
60
|
+
# lambda {|x| 10 / x rescue(puts $!)}
|
61
|
+
# end
|
62
|
+
def decorated_fof f1, f2
|
63
|
+
f1_clone = f1.to_s.dup
|
64
|
+
f1_clone.bump! '_' while method_defined? f1_clone
|
65
|
+
class_eval do
|
66
|
+
alias :"#{f1_clone}" :"#{f1}"
|
67
|
+
define_method(f1) {send(f2, &method(f1_clone))}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class Class
|
74
|
+
|
75
|
+
# define python-like initializer form
|
76
|
+
def __init__
|
77
|
+
modname, classname = name.rsplit('::', 2)
|
78
|
+
classname ||= modname
|
79
|
+
mod = '::'.in(name) ? eval(modname) : RMTools
|
80
|
+
mod.module_eval "def #{classname} *args; #{name}.new *args end
|
81
|
+
module_function :#{classname}"
|
82
|
+
if mod != RMTools
|
83
|
+
mod.each_child {|c| c.class_eval "include #{mod}; extend #{mod}" if !c.in c.children}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def method_proxy *vars
|
88
|
+
buffered_missing = instance_methods.grep(/method_missing/).sort.last || 'method_missing'
|
89
|
+
# next arg overrides previous
|
90
|
+
vars.each {|v|
|
91
|
+
class_eval "
|
92
|
+
alias #{buffered_missing.bump! '_'} method_missing
|
93
|
+
def method_missing *args, &block
|
94
|
+
#{v}.send *args, &block
|
95
|
+
rescue NoMethodError
|
96
|
+
#{buffered_missing} *args, &block
|
97
|
+
end"
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def personal_methods filter=//
|
102
|
+
(self.singleton_methods - self.superclass.singleton_methods).sort!.grep(filter)
|
103
|
+
end
|
104
|
+
|
105
|
+
def my_instance_methods filter=//
|
106
|
+
(self.public_instance_methods - Object.public_instance_methods).sort!.grep(filter)
|
107
|
+
end
|
108
|
+
|
109
|
+
def personal_instance_methods filter=//
|
110
|
+
(self.public_instance_methods - self.superclass.public_instance_methods).sort!.grep(filter)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Integer
|
3
|
+
|
4
|
+
def digits
|
5
|
+
nums = []
|
6
|
+
while (int ||= self) > 0
|
7
|
+
nums << int%10
|
8
|
+
int /= 10
|
9
|
+
end
|
10
|
+
nums
|
11
|
+
end
|
12
|
+
|
13
|
+
def mult_of(subj) # allready implemented in ActiveSupport though
|
14
|
+
self%subj == 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def each_bit # descending order
|
18
|
+
to_s(2).each_byte {|b| yield(b == 49)}
|
19
|
+
end
|
20
|
+
|
21
|
+
def blur_bm
|
22
|
+
to_s(2).gsub(/.?1.?/) {|m| m.size==3?'111':'11'}.to_i(2)
|
23
|
+
end
|
24
|
+
|
25
|
+
def hex
|
26
|
+
sprintf "%x", self
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_array(base=10)
|
30
|
+
int = self
|
31
|
+
ary = []
|
32
|
+
begin
|
33
|
+
a = int.divmod base
|
34
|
+
ary << a[1]
|
35
|
+
int = a[0]
|
36
|
+
end while int != 0
|
37
|
+
ary.reverse!
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class Numeric
|
43
|
+
|
44
|
+
def ceil_to(i)
|
45
|
+
self + i - self%i
|
46
|
+
end
|
47
|
+
|
48
|
+
def floor_to(i)
|
49
|
+
self - self%i
|
50
|
+
end
|
51
|
+
|
52
|
+
def round_to(i)
|
53
|
+
[ceil_to(i), floor_to(i)].max
|
54
|
+
end
|
55
|
+
|
56
|
+
def between(min, max)
|
57
|
+
min < self and self < max
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
class Float
|
63
|
+
|
64
|
+
def partial(range=100)
|
65
|
+
return to_i.to_s if to_i == self
|
66
|
+
a = abs
|
67
|
+
(2..range-1).each {|i| (1..range).each {|j|
|
68
|
+
n = j.to_f/i
|
69
|
+
break if n > a
|
70
|
+
return "#{'-' if self != a}#{j}/#{i}" if n == a
|
71
|
+
} }
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
module Math
|
78
|
+
|
79
|
+
def logb(b, x) log(x)/log(b) end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Object
|
3
|
+
alias :resto :respond_to?
|
4
|
+
|
5
|
+
def requrie file
|
6
|
+
require file
|
7
|
+
end
|
8
|
+
#alias :requrie :require # most frequent typo, lol
|
9
|
+
|
10
|
+
def is klass
|
11
|
+
if Array === klass
|
12
|
+
instance_of?(Array) && self[0].instance_of?(klass[0])
|
13
|
+
else instance_of? klass
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def kinda klass
|
18
|
+
if Array === klass
|
19
|
+
kind_of?(Array) && self[0].kind_of?(klass[0])
|
20
|
+
else kind_of? klass
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def my_methods filter=//
|
25
|
+
(self.public_methods - Object.public_instance_methods).sort!.grep(filter)
|
26
|
+
end
|
27
|
+
|
28
|
+
def personal_methods filter=//
|
29
|
+
(self.public_methods - self.class.superclass.public_instance_methods).sort!.grep(filter)
|
30
|
+
end
|
31
|
+
|
32
|
+
def my_methods_with params
|
33
|
+
m = my_methods
|
34
|
+
params.each {|p,val| m.reject! {|_| ''.method(_).send(p) != val}}
|
35
|
+
m
|
36
|
+
end
|
37
|
+
|
38
|
+
def personal_methods_with params
|
39
|
+
m = personal_methods
|
40
|
+
params.each {|p,val| m.reject! {|_| ''.method(_).send(p) != val}}
|
41
|
+
m
|
42
|
+
end
|
43
|
+
|
44
|
+
def readable_variables
|
45
|
+
public_methods.to_ss & instance_variables.map(&'[1..-1]')
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_from(obj)
|
49
|
+
readable_variables.each {|v| instance_variable_set("@#{v}", obj.instance_variable_get("@#{v}"))}
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def in *container
|
54
|
+
container.size == 1 ? container[0].include?(self) : container.include?(self)
|
55
|
+
end
|
56
|
+
|
57
|
+
def require! file
|
58
|
+
%w{.rb .so .dll}.each {|ext| $".delete "#{file}#{ext}"}
|
59
|
+
require file
|
60
|
+
end
|
61
|
+
|
62
|
+
def b; self end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class BlackHole
|
67
|
+
|
68
|
+
# Think twice before use it. It may devour your code!
|
69
|
+
def method_missing *args
|
70
|
+
BlackHole.new
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|