rmtools 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +84 -26
- data/Rakefile +7 -4
- data/ext/extconf.rb +1 -1
- data/ext/rmtools.cpp +27 -12
- data/ext/rmtools.h +6 -5
- data/lib/rmtools/b.rb +18 -0
- data/lib/rmtools/console/coloring.rb +72 -0
- data/lib/rmtools/console/highlight.rb +13 -0
- data/lib/rmtools/{printing.rb → console/printing.rb} +17 -2
- data/lib/rmtools/console.rb +1 -0
- data/lib/rmtools/conversions/enum.rb +23 -0
- data/lib/rmtools/conversions/int.rb +47 -0
- data/lib/rmtools/conversions/string.rb +26 -0
- data/lib/rmtools/conversions.rb +1 -0
- data/lib/rmtools/core/arguments.rb +52 -0
- data/lib/rmtools/{boolean.rb → core/boolean.rb} +0 -13
- data/lib/rmtools/core/class.rb +41 -0
- data/lib/rmtools/core/js.rb +45 -0
- data/lib/rmtools/core/kernel.rb +28 -0
- data/lib/rmtools/{module.rb → core/module.rb} +0 -41
- data/lib/rmtools/core/numeric.rb +35 -0
- data/lib/rmtools/{object.rb → core/object.rb} +2 -23
- data/lib/rmtools/core/proc.rb +18 -0
- data/lib/rmtools/core/regexp.rb +11 -0
- data/lib/rmtools/core/string_compliance.rb +31 -0
- data/lib/rmtools/core.rb +1 -0
- data/lib/rmtools/db/active_record.rb +54 -0
- data/lib/rmtools/db.rb +7 -0
- data/lib/rmtools/debug/binding.rb +56 -0
- data/lib/rmtools/debug/highlight.rb +23 -0
- data/lib/rmtools/debug/logging.rb +176 -0
- data/lib/rmtools/debug/present.rb +38 -0
- data/lib/rmtools/debug/timer.rb +19 -0
- data/lib/rmtools/debug/traceback.rb +92 -0
- data/lib/rmtools/debug.rb +1 -0
- data/lib/rmtools/debug_notrace.rb +1 -0
- data/lib/rmtools/enumerable/array.rb +134 -0
- data/lib/rmtools/enumerable/array_iterators.rb +33 -0
- data/lib/rmtools/enumerable/common.rb +49 -0
- data/lib/rmtools/{hash.rb → enumerable/hash.rb} +8 -8
- data/lib/rmtools/enumerable/object_space.rb +19 -0
- data/lib/rmtools/enumerable/range.rb +201 -0
- data/lib/rmtools/enumerable.rb +1 -0
- data/lib/rmtools/experimental/blackhole.rb +12 -0
- data/lib/rmtools/experimental/deprecation.rb +36 -0
- data/lib/rmtools/experimental/dumps.rb +28 -0
- data/lib/rmtools/{numeric.rb → experimental/numeric.rb} +22 -51
- data/lib/rmtools/experimental/rails_backtrace.rb +29 -0
- data/lib/rmtools/experimental/string.rb +56 -0
- data/lib/rmtools/{tree.rb → experimental/tree.rb} +0 -0
- data/lib/rmtools/experimental.rb +1 -0
- data/lib/rmtools/fs/dir.rb +89 -0
- data/lib/rmtools/fs/file.rb +104 -0
- data/lib/rmtools/fs/io.rb +58 -0
- data/lib/rmtools/fs/tools.rb +49 -0
- data/lib/rmtools/fs.rb +1 -0
- data/lib/rmtools/functional/fold.rb +32 -0
- data/lib/rmtools/{string_to_proc.rb → functional/string_to_proc.rb} +2 -22
- data/lib/rmtools/functional/unfold.rb +16 -0
- data/lib/rmtools/functional.rb +1 -0
- data/lib/rmtools/ip/numeric.rb +35 -0
- data/lib/rmtools/ip/string.rb +45 -0
- data/lib/rmtools/ip.rb +1 -0
- data/lib/rmtools/lang/ansi.rb +17 -0
- data/lib/rmtools/lang/cyrillic.rb +106 -0
- data/lib/rmtools/lang/regexp.rb +8 -0
- data/lib/rmtools/lang/shortcuts.rb +20 -0
- data/lib/rmtools/lang.rb +1 -0
- data/lib/rmtools/rand/array.rb +39 -0
- data/lib/rmtools/rand/enum.rb +26 -0
- data/lib/rmtools/rand/range.rb +13 -0
- data/lib/rmtools/{random.rb → rand/string.rb} +13 -107
- data/lib/rmtools/rand.rb +1 -0
- data/lib/rmtools/require.rb +13 -0
- data/lib/rmtools/setup.rb +6 -5
- data/lib/rmtools/text/string_parse.rb +60 -0
- data/lib/rmtools/{stringscanner.rb → text/string_scanner.rb} +3 -2
- data/lib/rmtools/text/string_simple.rb +75 -0
- data/lib/rmtools/text/string_split.rb +148 -0
- data/lib/rmtools/text/textilize.rb +44 -0
- data/lib/rmtools/text.rb +1 -0
- data/lib/rmtools/time/global.rb +17 -0
- data/lib/rmtools/time/russian.rb +47 -0
- data/lib/rmtools/time.rb +1 -32
- data/lib/rmtools/xml/document.rb +28 -0
- data/lib/rmtools/xml/finders.rb +84 -0
- data/lib/rmtools/xml/libxml.rb +11 -0
- data/lib/rmtools/xml/node.rb +196 -0
- data/lib/rmtools/xml/string.rb +43 -0
- data/lib/rmtools/xml/xpath.rb +32 -0
- data/lib/rmtools/xml.rb +7 -0
- data/lib/rmtools.rb +8 -44
- metadata +97 -72
- data/lib/rmtools/arguments.rb +0 -24
- data/lib/rmtools/array.rb +0 -189
- data/lib/rmtools/binding.rb +0 -23
- data/lib/rmtools/coloring.rb +0 -82
- data/lib/rmtools/cyr-time.rb +0 -49
- data/lib/rmtools/cyrilic.rb +0 -124
- data/lib/rmtools/dumps.rb +0 -192
- data/lib/rmtools/enum.rb +0 -90
- data/lib/rmtools/io.rb +0 -303
- data/lib/rmtools/js.rb +0 -25
- data/lib/rmtools/limited_string.rb +0 -17
- data/lib/rmtools/logging.rb +0 -158
- data/lib/rmtools/proc.rb +0 -25
- data/lib/rmtools/range.rb +0 -100
- data/lib/rmtools/string.rb +0 -276
- data/lib/rmtools/traceback.rb +0 -106
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kernel
|
2
|
+
|
3
|
+
# re-require
|
4
|
+
def require!(file)
|
5
|
+
%w{.rb .so .dll}.each {|ext| $".delete "#{file}#{ext}"}
|
6
|
+
require file
|
7
|
+
end
|
8
|
+
|
9
|
+
def obtained(obj, &func)
|
10
|
+
if obj.is Proc
|
11
|
+
if obj.arity == 0
|
12
|
+
func.call obj.call
|
13
|
+
else # obj is a function receiving another function
|
14
|
+
obj.call &func
|
15
|
+
end
|
16
|
+
else func.call obj
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def TypeError! given, *expected
|
21
|
+
"invalid argument type #{given.class.name}, expected #{expected*' or '}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def executing? file=$0
|
25
|
+
caller(0)[0] =~ /^#{file}:/
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -70,44 +70,3 @@ private
|
|
70
70
|
|
71
71
|
end
|
72
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,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Numeric
|
3
|
+
|
4
|
+
def ceil_to(i)
|
5
|
+
self + i - self%i
|
6
|
+
end
|
7
|
+
|
8
|
+
def floor_to(i)
|
9
|
+
self - self%i
|
10
|
+
end
|
11
|
+
|
12
|
+
def round_to(i)
|
13
|
+
[ceil_to(i), floor_to(i)].max
|
14
|
+
end
|
15
|
+
|
16
|
+
def between(min, max)
|
17
|
+
min < self and self < max
|
18
|
+
end
|
19
|
+
|
20
|
+
def mult_of(subj)
|
21
|
+
self%subj == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def hex
|
25
|
+
sprintf "%x", self
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module Math
|
31
|
+
|
32
|
+
def logb(b, x) log(x)/log(b) end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
@@ -1,11 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
class Object
|
3
3
|
alias :resto :respond_to?
|
4
|
-
|
5
|
-
def requrie file
|
6
|
-
require file
|
7
|
-
end
|
8
|
-
#alias :requrie :require # most frequent typo, lol
|
4
|
+
alias :requrie :require # most frequent typo, lol
|
9
5
|
|
10
6
|
def is klass
|
11
7
|
if Array === klass
|
@@ -50,25 +46,8 @@ class Object
|
|
50
46
|
self
|
51
47
|
end
|
52
48
|
|
53
|
-
def in
|
49
|
+
def in(*container)
|
54
50
|
container.size == 1 ? container[0].include?(self) : container.include?(self)
|
55
51
|
end
|
56
52
|
|
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
53
|
end
|
74
|
-
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Proc
|
3
|
+
NULL = lambda {} unless defined? Proc::NULL
|
4
|
+
attr_accessor :string
|
5
|
+
|
6
|
+
def when
|
7
|
+
Thread.new do
|
8
|
+
sleep 0.001 until yield
|
9
|
+
call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.eval string, binding=nil
|
14
|
+
(proc = (binding || Kernel).eval "lambda {#{string}}").string = string
|
15
|
+
proc
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
if RUBY_VERSION < "1.9"
|
4
|
+
def ord; self[0] end
|
5
|
+
else
|
6
|
+
# BUGFIX?
|
7
|
+
alias :sub19 :sub
|
8
|
+
alias :sub19! :sub!
|
9
|
+
alias :gsub19 :gsub
|
10
|
+
alias :gsub19! :gsub!
|
11
|
+
|
12
|
+
def sub! a,b=nil,&c
|
13
|
+
if b
|
14
|
+
if b=~/\\\d/
|
15
|
+
b = b.sub19!(/\\\d/) {|m| "\#{$#{m[1,1]}}"}
|
16
|
+
sub19!(a) {eval "\"#{b}\""}
|
17
|
+
else sub19!(a) {b} end
|
18
|
+
else sub19! a,&c end
|
19
|
+
end
|
20
|
+
|
21
|
+
def sub a,b=nil,&c
|
22
|
+
if b
|
23
|
+
if b=~/\\\d/
|
24
|
+
b = b.sub19(/\\\d/) {|m| "\#{$#{m[1,1]}}"}
|
25
|
+
sub19(a) {eval "\"#{b}\""}
|
26
|
+
else sub19(a) {b} end
|
27
|
+
else sub19 a,&c end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/lib/rmtools/core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_with_path __FILE__, '*'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
|
5
|
+
def self.establish_connection_with config
|
6
|
+
c = case config
|
7
|
+
when String
|
8
|
+
c = if config.inline
|
9
|
+
if c = RMTools.read(config) then c
|
10
|
+
else return; nil
|
11
|
+
end
|
12
|
+
else config
|
13
|
+
end
|
14
|
+
YAML.load c
|
15
|
+
when IO then YAML.load config
|
16
|
+
else config
|
17
|
+
end
|
18
|
+
Base.establish_connection(c) rescue(false)
|
19
|
+
end
|
20
|
+
|
21
|
+
class Base
|
22
|
+
|
23
|
+
def self.establish_connection_with config
|
24
|
+
ActiveRecord.establish_connection_with config
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
serializer = Serializer.new(self)
|
29
|
+
serializer.respond_to?(:attributes_hash) ?
|
30
|
+
serializer.attributes_hash :
|
31
|
+
serializer.serializable_record
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :delete_with_id :delete
|
35
|
+
# a problem was: model.delete() won't work if it has no id. Just delete() it if has
|
36
|
+
def delete
|
37
|
+
id ? delete_with_id : self.class.delete_all(attributes)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.merge_conditions(*conditions)
|
41
|
+
segments = conditions.map {|condition|
|
42
|
+
sanitize_sql condition
|
43
|
+
}.reject {|condition|
|
44
|
+
condition.blank?
|
45
|
+
}
|
46
|
+
"(#{segments.join(') AND (')})" unless segments.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
data/lib/rmtools/db.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
class Binding
|
2
|
+
|
3
|
+
def inspect_local_variables
|
4
|
+
vars = self.eval('local_variables') # ['a', 'b']
|
5
|
+
values = self.eval "[#{vars * ','}]" # ["a's value", "b's value"]
|
6
|
+
Hash[vars.zip(values)]
|
7
|
+
end
|
8
|
+
|
9
|
+
def inspect_instance_variables
|
10
|
+
vars = self.eval('instance_variables') # ['@a', '@b']
|
11
|
+
values = self.eval "[#{vars * ','}]" # ["@a's value", "@b's value"]
|
12
|
+
Hash[vars.zip(values)]
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect_env
|
16
|
+
self.eval("{'self' => self}").merge(inspect_local_variables).merge(inspect_instance_variables)
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid_types(pattern_ary)
|
20
|
+
self.eval("[#{self.eval('local_variables')*','}]").valid_types(pattern_ary)
|
21
|
+
end
|
22
|
+
|
23
|
+
def report(obj)
|
24
|
+
if Array === obj
|
25
|
+
obj.map {|s| self.eval "\"#{s.gsub('"'){'\"'}} = \#{(#{s}).inspect}\""} * '; '
|
26
|
+
else
|
27
|
+
obj.to_s.split(' ').map {|s| self.eval "\"#{s.gsub('"'){'\"'}} = \#{(#{s}).inspect}\""} * '; '
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# it's supposed to be called during TDD in an IRB session
|
32
|
+
# $__MAIN__ must be `self' or root IRB session, i.e. `main' object
|
33
|
+
# def tested_function
|
34
|
+
# blah blah blah
|
35
|
+
# rescue => err
|
36
|
+
# binding.start_interaction
|
37
|
+
# raise err
|
38
|
+
# end
|
39
|
+
def start_interaction(sandbox=true)
|
40
|
+
$__env__ = inspect_env
|
41
|
+
Kernel.puts RMTools.format_trace(caller(2)).join("\n")
|
42
|
+
$env.present
|
43
|
+
$__binding__ = self
|
44
|
+
|
45
|
+
$log << "entering irb"
|
46
|
+
$__MAIN__.irb
|
47
|
+
# Now input "irb_change_binding$__binding__" and have fun with debug
|
48
|
+
$log << "exiting irb"
|
49
|
+
|
50
|
+
if sandbox
|
51
|
+
self.eval($env.keys.map {|k, v| "#{k} = $env[#{k.inspect}]"} * '; ')
|
52
|
+
end
|
53
|
+
$__env__ = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_with_path 'console/coloring'
|
2
|
+
|
3
|
+
module RMTools
|
4
|
+
|
5
|
+
def highlighted_line(file, line)
|
6
|
+
if defined? SCRIPT_LINES__
|
7
|
+
" >> #{Painter.green SCRIPT_LINES__[file][line.to_i - 1].chop}" if SCRIPT_LINES__[file]
|
8
|
+
else
|
9
|
+
file = Readline::TEMPLOG if file == '(irb)' and defined? Readline::TEMPLOG
|
10
|
+
" >> #{Painter.green read_lines(file, line.to_i).chop}" if File.file? file
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module_function :highlighted_line
|
15
|
+
end
|
16
|
+
|
17
|
+
class Proc
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#{str=to_s}: #{@string ? Painter.green(@string) : "\n"+RMTools.highlighted_line(*str.match(/([^@]+):(\d+)>$/)[1..2])}"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_with_path 'console/coloring'
|
3
|
+
require_with_path 'text/string_parse'
|
4
|
+
|
5
|
+
module RMTools
|
6
|
+
|
7
|
+
# lazy logger
|
8
|
+
# with caller processing and highlighting
|
9
|
+
class RMLogger
|
10
|
+
__init__
|
11
|
+
attr_accessor :mute_info, :mute_warn, :mute_log, :mute_debug
|
12
|
+
attr_reader :default_format
|
13
|
+
|
14
|
+
Modes = %w{debug log info warn}.to_syms
|
15
|
+
NOPRINT = 4
|
16
|
+
NOLOG = 2
|
17
|
+
INLINE = 1
|
18
|
+
|
19
|
+
def initialize format={}
|
20
|
+
@clr = Coloring.new
|
21
|
+
@highlight = {
|
22
|
+
:warn => @clr.red_bold("WARN"),
|
23
|
+
:log => @clr.cyan("INFO"),
|
24
|
+
:info => @clr.cyan_bold("INFO"),
|
25
|
+
:debug => @clr.gray_bold("DEBUG")
|
26
|
+
}
|
27
|
+
@file_formats = Hash.new(@default_format = {})
|
28
|
+
set_format :global, format
|
29
|
+
end
|
30
|
+
|
31
|
+
def _set_format file, format
|
32
|
+
file.print = !format.q
|
33
|
+
file.out = format.out
|
34
|
+
|
35
|
+
file.path_format = '%'.in file.out if file.out
|
36
|
+
file.tf = format.time.to_a
|
37
|
+
file.cf0 = format.caller
|
38
|
+
file.cf = file.cf0.sub('%p'){'\1'}.sub('%f'){'\2'}.sub('%l'){'\3'}.sub('%m'){'\4'}
|
39
|
+
file.fmt = format.format
|
40
|
+
file._time, file._caller = '%time'.in(file.fmt), '%caller'.in(file.fmt)
|
41
|
+
end
|
42
|
+
|
43
|
+
def defaults
|
44
|
+
puts %{ :q => false, # not print
|
45
|
+
:out => false, # output to file, may have strftime's %H%M%Y for filename
|
46
|
+
:time => ["%H:%M:%S", "%03d"], # strftime, [msecs]
|
47
|
+
:caller => "#{@clr.gray('%f:%l')} #{@clr.red_bold(':%m')}", # file:line :method
|
48
|
+
:format => "%time %mode [%caller]: %text" # no comments}
|
49
|
+
end
|
50
|
+
|
51
|
+
# set any needed params, the rest will be set by default
|
52
|
+
def set_format *args
|
53
|
+
global, format = args.fetch_opts [nil],
|
54
|
+
:time => ["%H:%M:%S", "%03d"],
|
55
|
+
:caller => "#{@clr.gray('%f:%l')} #{@clr.red_bold(':%m')}",
|
56
|
+
:format => "%time %mode [%caller]: %text"
|
57
|
+
if global
|
58
|
+
_set_format @default_format, format
|
59
|
+
else
|
60
|
+
_set_format(file_format={}, format)
|
61
|
+
@file_formats[File.expand_path(caller[0].till ':')] = file_format
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_format file=nil
|
66
|
+
cfg = @file_formats[file && File.expand_path(file)]
|
67
|
+
modes = Modes.reject {|m| send :"mute_#{m}"}
|
68
|
+
%{<Logger #{cfg.fmt.sub('%time', "%time(#{cfg.tf*'.'})").sub('%caller', "%caller(#{cfg.cf0})")}#{' -> '+cfg.out if cfg.out} #{modes.b ? modes.inspect : 'muted'}>}
|
69
|
+
end
|
70
|
+
|
71
|
+
def _print mode, text, opts, caler, bind, cfg
|
72
|
+
log_ = opts&NOLOG==0
|
73
|
+
print_ = opts&NOPRINT==0
|
74
|
+
str = cfg.fmt.dup
|
75
|
+
str.sub! "%mode", @highlight[mode]
|
76
|
+
if bind
|
77
|
+
text = bind.report text
|
78
|
+
elsif !text.is String
|
79
|
+
text = text.inspect
|
80
|
+
end
|
81
|
+
str.sub! "%text", text
|
82
|
+
str << "\n" if opts&INLINE==0
|
83
|
+
out = cfg.out
|
84
|
+
if cfg._time or cfg.path_format
|
85
|
+
now = Time.now
|
86
|
+
if cfg._time
|
87
|
+
time = now.strftime cfg.tf[0]
|
88
|
+
time << ".#{cfg.tf[1]%[now.usec/1000]}" if cfg.tf[1]
|
89
|
+
str.sub! "%time", time
|
90
|
+
end
|
91
|
+
out = now.strftime cfg.out if cfg.path_format
|
92
|
+
end
|
93
|
+
str.sub! "%caller", caler.sub(String::CALLER_RE, cfg.cf) if caler
|
94
|
+
log_str = @clr.clean str
|
95
|
+
RMTools.write out, log_str if log_
|
96
|
+
Kernel.print str if print_
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_binding a
|
100
|
+
a[0].is(Binding) ? [a[0], a[1] || 0] : [nil, a[0] || 0]
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_config!
|
104
|
+
@file_formats.empty? ? @default_format : @file_formats[File.expand_path(caller(2)[0].till ':')]
|
105
|
+
end
|
106
|
+
|
107
|
+
# controllers:
|
108
|
+
# - $panic: print debug messages
|
109
|
+
# - $verbose: print log messages
|
110
|
+
# - $quiet: print only warn messages regardless of other globals
|
111
|
+
# - @mute_warn, @mute_info, @mute_log: do not print
|
112
|
+
# this messages regardless of any globals
|
113
|
+
# - @out_all: write to file any messages
|
114
|
+
|
115
|
+
def warn text="\b\b ", *a
|
116
|
+
cfg = get_config!
|
117
|
+
if (cfg.out or cfg.print) && !@mute_warn
|
118
|
+
bind, opts = check_binding a
|
119
|
+
opts |= NOLOG if !cfg.out
|
120
|
+
opts |= NOPRINT if !cfg.print
|
121
|
+
text ||= yield if block_given?
|
122
|
+
_print(:warn, text, opts, cfg._caller && caller[0], bind, cfg)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def log text="\b\b ", *a
|
127
|
+
cfg = get_config!
|
128
|
+
if (cfg.out or cfg.print && !$quiet && $verbose) && !@mute_log
|
129
|
+
bind, opts = check_binding a
|
130
|
+
opts |= NOLOG if !cfg.out
|
131
|
+
opts |= NOPRINT if !(cfg.print && !$quiet && $verbose)
|
132
|
+
text ||= yield if block_given?
|
133
|
+
_print(:log, text, opts, cfg._caller && caller[0], bind, cfg)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def info text="\b\b ", *a
|
138
|
+
cfg = get_config!
|
139
|
+
if (cfg.print && !$quiet or cfg.out && cfg.out_all) && !@mute_info
|
140
|
+
bind, opts = check_binding a
|
141
|
+
opts |= NOLOG if !(cfg.out && cfg.out_all)
|
142
|
+
opts |= NOPRINT if !(cfg.print && !$quiet)
|
143
|
+
text ||= yield if block_given?
|
144
|
+
_print(:info, text, opts, cfg._caller && caller[0], bind, cfg)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def debug text="\b\b ", *a
|
149
|
+
cfg = get_config!
|
150
|
+
if (cfg.print && $panic && !$quiet or cfg.out && cfg.out_all) && !@mute_debug
|
151
|
+
bind, opts = check_binding a
|
152
|
+
opts |= NOLOG if !(cfg.out && cfg.out_all)
|
153
|
+
opts |= NOPRINT if !(cfg.print && $panic && !$quiet)
|
154
|
+
text ||= yield if block_given?
|
155
|
+
_print(:debug, text, opts, cfg._caller && caller[0], bind, cfg)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
alias << info
|
160
|
+
alias < warn
|
161
|
+
|
162
|
+
Modes.each {|m| define_method("#{m}=") {|mute| send :"mute_#{m}=", !mute}}
|
163
|
+
|
164
|
+
def outall=(x) @default_format.out_all = x end
|
165
|
+
def print=(x) @default_format.print = x end
|
166
|
+
def out=(x) @default_format.out = x end
|
167
|
+
|
168
|
+
def out_all() @default_format.out_all end
|
169
|
+
def print() @default_format.print end
|
170
|
+
def out() @default_format.out end
|
171
|
+
|
172
|
+
def inspect() get_format end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Object
|
3
|
+
|
4
|
+
def present
|
5
|
+
Hash[readable_variables.map {|v| [":#{v}", __send__(v)]}].present
|
6
|
+
end
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class Array
|
11
|
+
|
12
|
+
def present(inspect_string=nil)
|
13
|
+
res = "[ "
|
14
|
+
indent = (size-1).to_s.size
|
15
|
+
res << map_with_index {|k,i|
|
16
|
+
"#{i.to_s.rjust(indent)}: #{(k.is String and !inspect_string) ? k : k.inspect}"
|
17
|
+
}*"\n "
|
18
|
+
res << "]"
|
19
|
+
puts res
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class Hash
|
25
|
+
|
26
|
+
def present(inspect_string=nil)
|
27
|
+
str = "{ "
|
28
|
+
sorted = sort rescue to_a.sort_by_to_s
|
29
|
+
str << sorted.map {|k,v|
|
30
|
+
"#{(k.is String and !inspect_string) ? k : k.inspect} => #{(v.is String and !inspect_string) ? v : v.inspect},"
|
31
|
+
}*"\n "
|
32
|
+
str << "}"
|
33
|
+
puts str
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_with_path 'console/coloring'
|
2
|
+
|
3
|
+
module RMTools
|
4
|
+
|
5
|
+
def timer(ts=1, output=true)
|
6
|
+
timez = ts - 1
|
7
|
+
panic, verbose = $panic, $verbose
|
8
|
+
$panic = $verbose = false
|
9
|
+
t1 = Time.now
|
10
|
+
timez.times {yield}
|
11
|
+
res = yield
|
12
|
+
t2 = (Time.now.to_f*1000).round
|
13
|
+
t1 = (t1.to_f*1000).round
|
14
|
+
$panic, $verbose = panic, verbose
|
15
|
+
res = res.inspect
|
16
|
+
puts "#{output ? "res: #{res.size > 1000 ? res[0...1000]+"…" : res}\n" : "size of res string: #{res.to_s.size}, "}one: #{Painter.gray '%0.4fms'%[(t2-t1).to_f/ts]}, total: #{Painter.gray "#{(t2-t1).to_f}ms"}"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require_with_path 'debug/highlight'
|
2
|
+
module Kernel
|
3
|
+
|
4
|
+
# Python-like traceback for exceptions; uses ANSI coloring.
|
5
|
+
# In case of any low-level ruby error it may hang up interpreter
|
6
|
+
# (although you must have done creepy things for that). If you find
|
7
|
+
# interpreter in hanging up, require 'rmtools_notrace' instead of 'rmtools'
|
8
|
+
# or run "Exception.trace_format false" right after require
|
9
|
+
#
|
10
|
+
# 1:0> def divbyzero
|
11
|
+
# 2:1< 10/0 end
|
12
|
+
# => nil
|
13
|
+
# 3:0> divbyzero
|
14
|
+
# ZeroDivisionError: divided by 0
|
15
|
+
# from (irb):2:in `divbyzero' <- `/'
|
16
|
+
# >> 10/0 end
|
17
|
+
# from (irb):3
|
18
|
+
# >> divbyzero
|
19
|
+
def format_trace a
|
20
|
+
bt, calls, i = [], [], 0
|
21
|
+
# $log.info 'a.size', binding
|
22
|
+
m = a[0].parse:caller
|
23
|
+
while i < a.size
|
24
|
+
# $log.info i
|
25
|
+
m2 = a[i+1] && a[i+1].parse(:caller)
|
26
|
+
# $log.info 'm', binding
|
27
|
+
# $log.info 'm2', binding
|
28
|
+
# $log.info 'm[3] m[1..2]==m2[1..2]', binding if m and m2
|
29
|
+
# $log.info 'm[1] m[2]', binding if m
|
30
|
+
# $log.info highlighted_line(*m[1..2]) if m
|
31
|
+
if m and m.func and m2 and [m.path, m.line] == [m2.path, m2.line]
|
32
|
+
calls << "`#{m.func}' -> "
|
33
|
+
elsif m and m.line != 0 and line = highlighted_line(m.path, m.line)
|
34
|
+
bt << "#{a[i]}#{calls.join}\n#{line}"
|
35
|
+
calls = []
|
36
|
+
else bt << a[i]
|
37
|
+
end
|
38
|
+
i += 1
|
39
|
+
m = m2
|
40
|
+
end
|
41
|
+
# $log << Painter.r("FORMAT DONE! #{bt.size} lines formatted")
|
42
|
+
bt
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
class Class
|
48
|
+
|
49
|
+
def trace_format method
|
50
|
+
if Exception.in ancestors
|
51
|
+
class_eval(method ? %{
|
52
|
+
def set_backtrace src
|
53
|
+
src = #{method} src
|
54
|
+
set_bt src
|
55
|
+
end
|
56
|
+
} : %{
|
57
|
+
def set_backtrace src
|
58
|
+
set_bt src
|
59
|
+
end
|
60
|
+
})
|
61
|
+
else
|
62
|
+
raise NoMethodError, "undefined method `trace_format' for class #{self}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# 1.9 may hung up processing IO while generating traceback
|
69
|
+
if RUBY_VERSION < '1.9'
|
70
|
+
class Exception
|
71
|
+
alias :set_bt :set_backtrace
|
72
|
+
|
73
|
+
# to use trace formatting ensure that you have SCRIPT_LINES__ constant set
|
74
|
+
# SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
75
|
+
#
|
76
|
+
# If you also set (e.g. in irbrc file)
|
77
|
+
# module Readline
|
78
|
+
# alias :orig_readline :readline
|
79
|
+
# def readline(*args)
|
80
|
+
# ln = orig_readline(*args)
|
81
|
+
# SCRIPT_LINES__['(irb)'] << "#{ln}\n"
|
82
|
+
# ln
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
# it will be possible to get the lines entered in IRB
|
86
|
+
# else it reads only ordinal require'd files
|
87
|
+
|
88
|
+
trace_format :format_trace
|
89
|
+
end
|
90
|
+
|
91
|
+
SystemStackError.trace_format false
|
92
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_with_path __FILE__, '*'
|
@@ -0,0 +1 @@
|
|
1
|
+
require_with_path 'debug', '{binding,logging,present,timer}'
|