rmtools 1.2.3 → 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +1 -1
- data/Rakefile +3 -3
- data/ext/rmtools.cpp +8 -8
- data/lib/rmtools/b.rb +3 -0
- data/lib/rmtools/console/coloring.rb +7 -3
- data/lib/rmtools/conversions/enum.rb +1 -1
- data/lib/rmtools/conversions/json.rb +49 -0
- data/lib/rmtools/conversions/string.rb +1 -7
- data/lib/rmtools/core/boolean.rb +4 -0
- data/lib/rmtools/core/class.rb +3 -2
- data/lib/rmtools/core/js.rb +12 -1
- data/lib/rmtools/core/module.rb +1 -1
- data/lib/rmtools/core/proc.rb +2 -0
- data/lib/rmtools/db.rb +5 -1
- data/lib/rmtools/db/active_record.rb +40 -0
- data/lib/rmtools/dev/blackhole.rb +10 -2
- data/lib/rmtools/dev/code_reader.rb +2 -2
- data/lib/rmtools/dev/logging.rb +27 -13
- data/lib/rmtools/dev/timer.rb +8 -4
- data/lib/rmtools/enumerable/array.rb +63 -1
- data/lib/rmtools/enumerable/array_iterators.rb +5 -3
- data/lib/rmtools/enumerable/range.rb +11 -1
- data/lib/rmtools/fs/file.rb +50 -35
- data/lib/rmtools/fs/io.rb +2 -2
- data/lib/rmtools/install.rb +9 -11
- data/lib/rmtools/lang/ansi.rb +25 -2
- data/lib/rmtools/lang/cyrillic.rb +20 -21
- data/lib/rmtools/lang/regexp.rb +5 -2
- data/lib/rmtools/text/regexp.rb +1 -1
- data/lib/rmtools/text/string_parse.rb +1 -1
- data/lib/rmtools/text/string_simple.rb +9 -0
- data/lib/rmtools/text/string_split.rb +33 -8
- data/lib/rmtools/xml/string.rb +1 -1
- data/lib/rmtools/xml/xpath.rb +2 -0
- metadata +8 -10
- data/lib/rmtools/lang/helpers.rb +0 -24
data/Manifest.txt
CHANGED
@@ -40,7 +40,6 @@ lib/rmtools/core/deprecation.rb
|
|
40
40
|
lib/rmtools/core/regexp.rb
|
41
41
|
lib/rmtools/core/class.rb
|
42
42
|
lib/rmtools/core/proc.rb
|
43
|
-
lib/rmtools/lang/helpers.rb
|
44
43
|
lib/rmtools/lang/ansi.rb
|
45
44
|
lib/rmtools/lang/regexp.rb
|
46
45
|
lib/rmtools/lang/cyrillic.rb
|
@@ -84,6 +83,7 @@ lib/rmtools/enumerable/array_iterators.rb
|
|
84
83
|
lib/rmtools/require.rb
|
85
84
|
lib/rmtools/xml.rb
|
86
85
|
lib/rmtools/conversions.rb
|
86
|
+
lib/rmtools/conversions/json.rb
|
87
87
|
lib/rmtools/conversions/string.rb
|
88
88
|
lib/rmtools/conversions/enum.rb
|
89
89
|
lib/rmtools/conversions/int.rb
|
data/Rakefile
CHANGED
@@ -2,14 +2,14 @@ require 'rake'
|
|
2
2
|
require 'lib/rmtools/install'
|
3
3
|
compile_manifest
|
4
4
|
|
5
|
-
RMTOOLS_VERSION = '1.2.
|
5
|
+
RMTOOLS_VERSION = '1.2.7'
|
6
6
|
begin
|
7
7
|
require 'hoe'
|
8
8
|
config = Hoe.spec 'rmtools' do
|
9
9
|
developer("Shinku", "tinbka@gmail.com")
|
10
10
|
|
11
|
-
self.summary = 'Yet another Ruby applied
|
12
|
-
self.description = 'Applied
|
11
|
+
self.summary = 'Yet another Ruby applied lib'
|
12
|
+
self.description = 'Applied library primarily for debug and text/arrays/files processing purposes.'
|
13
13
|
self.changes = paragraphs_of('README.txt', 5..-1).join("\n\n")
|
14
14
|
self.url = 'http://github.com/tinbka'
|
15
15
|
|
data/ext/rmtools.cpp
CHANGED
@@ -234,23 +234,23 @@ static VALUE rb_ary_uniq_by(VALUE ary)
|
|
234
234
|
/*
|
235
235
|
* Make hash with unique items of +self+ or (when block given)
|
236
236
|
* unique results of items yield for keys and
|
237
|
-
* count of them in +self
|
237
|
+
* count of them in +self+,
|
238
238
|
* or (with option :fill) arrays of yield results,
|
239
239
|
* or (with option :indexes) arrays of indexes of them,
|
240
240
|
* or (with option :group) arrays of themselves for values
|
241
241
|
*
|
242
|
-
* [1, 2, 2, 2, 3, 3].
|
242
|
+
* [1, 2, 2, 2, 3, 3].arrange
|
243
243
|
* => {1=>1, 2=>3, 3=>2}
|
244
|
-
* [1, 2, 2, 2, 3, 3].
|
244
|
+
* [1, 2, 2, 2, 3, 3].arrange {|i| i%2}
|
245
245
|
* => {0=>3, 1=>3}
|
246
|
-
* [1, 2, 2, 2, 3, 3].
|
246
|
+
* [1, 2, 2, 2, 3, 3].arrange :fill
|
247
247
|
* => {1=>[1], 2=>[2, 2, 2], 3=>[3, 3]}
|
248
|
-
* [1, 2, 2, 2, 3, 3].
|
248
|
+
* [1, 2, 2, 2, 3, 3].arrange :indexes
|
249
249
|
* => {1=>[0], 2=>[1, 2, 3], 3=>[4, 5]}
|
250
|
-
* [1, 2, 2, 2, 3, 3].
|
250
|
+
* [1, 2, 2, 2, 3, 3].arrange(:indexes) {|i| i%2}
|
251
251
|
* => {0=>[1, 2, 3], 1=>[0, 4, 5]}
|
252
252
|
* :group is analogue to rails' group_by but twice faster
|
253
|
-
* [1, 2, 2, 2, 3, 3].
|
253
|
+
* [1, 2, 2, 2, 3, 3].arrange(:group) {|i| i%2}
|
254
254
|
* => {0=>[2, 2, 2], 1=>[1, 3, 3]}
|
255
255
|
*/
|
256
256
|
static VALUE rb_ary_count_items(int argc, VALUE *argv, VALUE ary)
|
@@ -539,7 +539,7 @@ extern "C" void Init_rmtools()
|
|
539
539
|
rb_define_method(rb_cArray, "uniq_by", RUBY_METHOD_FUNC(rb_ary_uniq_by), 0);
|
540
540
|
rb_define_method(rb_cArray, "uniq_by!", RUBY_METHOD_FUNC(rb_ary_uniq_by_bang), 0);
|
541
541
|
|
542
|
-
rb_define_method(rb_cArray, "
|
542
|
+
rb_define_method(rb_cArray, "arrange", RUBY_METHOD_FUNC(rb_ary_count_items), -1);
|
543
543
|
|
544
544
|
rb_define_method(rb_cArray, "partition", RUBY_METHOD_FUNC(rb_ary_partition), 0);
|
545
545
|
|
data/lib/rmtools/b.rb
CHANGED
@@ -19,8 +19,8 @@ module RMTools
|
|
19
19
|
CYAN = 36
|
20
20
|
GRAY = 37
|
21
21
|
|
22
|
-
Colors = {:black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :purple => 35, :cyan => 36, :gray => 37,
|
23
|
-
:k => 30, :r => 31, :g => 32, :y => 33, :b => 34, :p => 35, :c => 36
|
22
|
+
Colors = {:black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :purple => 35, :cyan => 36, :gray => 37, :pink => [35, 1],
|
23
|
+
:k => 30, :r => 31, :g => 32, :y => 33, :b => 34, :p => 35, :c => 36, :w => [37, 1]
|
24
24
|
}.unify_keys
|
25
25
|
Effects = {:bold => 1, :underline => 4, :graybg => 5, :boldbg => 7,
|
26
26
|
:b => 1, :u => 4, :gbg => 5, :bbg => 7
|
@@ -37,7 +37,11 @@ module RMTools
|
|
37
37
|
return str if ENV['ComSpec'] =~ /cmd(.exe)?$/
|
38
38
|
if num.is String
|
39
39
|
num = Colors[num]
|
40
|
-
|
40
|
+
if !num
|
41
|
+
effect = Effects[num]
|
42
|
+
elsif num.is Array
|
43
|
+
num, effect = num
|
44
|
+
end
|
41
45
|
end
|
42
46
|
effect = Effects[effect] if effect.is String
|
43
47
|
if num and effect
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<<-original
|
2
|
+
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
|
3
|
+
klass.class_eval do
|
4
|
+
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
|
5
|
+
def to_json(options = nil)
|
6
|
+
ActiveSupport::JSON.encode(self, options)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
original
|
11
|
+
# Overwrites slow ActiveSupport ActiveSupport::JSON.encode by faster 1.9 stdlib JSON library
|
12
|
+
if RUBY_VERSION > '1.9'
|
13
|
+
[Array, Hash].each do |klass|
|
14
|
+
klass.class_eval do
|
15
|
+
def to_json(options=nil)
|
16
|
+
JSON.unparse(self, options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ActiveSupport::OrderedHash
|
22
|
+
# nothing lost here since javascript engines (at least Webkit) doesn't order objects
|
23
|
+
def to_json(options=nil)
|
24
|
+
JSON.unparse({}.merge!(self), options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class String
|
29
|
+
# the opposite of #to_json
|
30
|
+
def from_json
|
31
|
+
JSON.parse self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
else
|
36
|
+
|
37
|
+
def from_json
|
38
|
+
ActiveSupport::JSON.decode self
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
class Object
|
44
|
+
|
45
|
+
def to_json_safe(options=nil)
|
46
|
+
timeout(10) {to_json(options)}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'cgi'
|
2
|
+
#require 'cgi'
|
3
3
|
|
4
4
|
class String
|
5
5
|
|
@@ -17,11 +17,5 @@ class String
|
|
17
17
|
}
|
18
18
|
h
|
19
19
|
end
|
20
|
-
|
21
|
-
# the opposite of #to_json
|
22
|
-
# active support activesupport
|
23
|
-
def from_json
|
24
|
-
ActiveSupport::JSON.decode self
|
25
|
-
end
|
26
20
|
|
27
21
|
end
|
data/lib/rmtools/core/boolean.rb
CHANGED
@@ -13,6 +13,8 @@ class TrueClass
|
|
13
13
|
def <= obj; !!obj or obj == true end
|
14
14
|
def > obj; !obj end
|
15
15
|
def >= obj; !obj or obj == true end
|
16
|
+
|
17
|
+
def call(*) self end
|
16
18
|
end
|
17
19
|
|
18
20
|
class FalseClass
|
@@ -29,6 +31,8 @@ class FalseClass
|
|
29
31
|
def <= obj; !obj.nil? end
|
30
32
|
def > obj; obj.nil? end
|
31
33
|
def >= obj; !obj end
|
34
|
+
|
35
|
+
def call(*) self end
|
32
36
|
end
|
33
37
|
|
34
38
|
class NilClass
|
data/lib/rmtools/core/class.rb
CHANGED
@@ -41,9 +41,10 @@ class Class
|
|
41
41
|
|
42
42
|
# differs with #ancestors in that it doesn't show included modules
|
43
43
|
def superclasses
|
44
|
-
unfold(lambda {|c|!c}) {|c| [c.superclass, c]}
|
44
|
+
superclass ? superclass.unfold(lambda {|c|!c}) {|c| [c.superclass, c]} : []
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
require 'set'
|
50
|
+
[Hash, Array, Set, Regexp, File, Dir, Range, Class, Module].each {|klass| klass.__init__}
|
data/lib/rmtools/core/js.rb
CHANGED
@@ -15,12 +15,23 @@ class Hash
|
|
15
15
|
str = method.to_s
|
16
16
|
if str =~ /=$/
|
17
17
|
self[str[0..-2]] = args[0]
|
18
|
+
elsif !args.empty? or str =~ /[!?]$/
|
19
|
+
throw_no method
|
18
20
|
else
|
19
|
-
throw_no method if !args.empty? or str =~ /[!?]$/
|
20
21
|
a = self[str]
|
21
22
|
(a == default) ? self[method] : a
|
22
23
|
end
|
23
24
|
end
|
25
|
+
|
26
|
+
# Redefine since these methods are deprecated anyway
|
27
|
+
def type
|
28
|
+
a = self['type']
|
29
|
+
(a == default) ? self[:type] : a
|
30
|
+
end
|
31
|
+
def id
|
32
|
+
a = self['id']
|
33
|
+
(a == default) ? self[:id] : a
|
34
|
+
end
|
24
35
|
|
25
36
|
end
|
26
37
|
|
data/lib/rmtools/core/module.rb
CHANGED
data/lib/rmtools/core/proc.rb
CHANGED
data/lib/rmtools/db.rb
CHANGED
@@ -6,7 +6,11 @@ begin
|
|
6
6
|
# fix for that mystic bug
|
7
7
|
# /usr/lib/ruby/1.8/openssl/ssl-internal.rb:30: [BUG] Segmentation fault
|
8
8
|
# ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-linux]
|
9
|
-
|
9
|
+
if RUBY_VERSION < '1.9.3'
|
10
|
+
require 'openssl/ssl'
|
11
|
+
else
|
12
|
+
require 'openssl'
|
13
|
+
end
|
10
14
|
rescue Exception
|
11
15
|
p $!
|
12
16
|
nil
|
@@ -89,6 +89,46 @@ module ActiveRecord
|
|
89
89
|
"#{self.class.name.tableize}/#{id}"
|
90
90
|
end
|
91
91
|
|
92
|
+
def self.select_rand(limit, options={})
|
93
|
+
cnt = options.delete :cnt
|
94
|
+
discnt = options.delete :discnt
|
95
|
+
where = options.delete :where
|
96
|
+
cnt_where = options.delete :cnt_where
|
97
|
+
tables = options.delete :tables
|
98
|
+
cnt_tables = options.delete :cnt_tables
|
99
|
+
fields = options.delete :fields
|
100
|
+
|
101
|
+
find_by_sql(["SELECT * FROM (
|
102
|
+
SELECT @cnt:=#{cnt ? cnt.to_i : 'COUNT(*)'}+1#{-discnt.to_i if discnt}, @lim:=#{limit.to_i}#{"FROM #{options[:cnt_tables] || table_name} WHERE #{cnt_where}" if !cnt}
|
103
|
+
) vars
|
104
|
+
STRAIGHT_JOIN (
|
105
|
+
SELECT #{fields || table_name+'.*'}, @lim:=@lim-1 FROM #{tables || table_name} WHERE (@cnt:=@cnt-1) AND RAND() < @lim/@cnt#{" AND (#{where})" if where}
|
106
|
+
) i", options])
|
107
|
+
end
|
108
|
+
|
109
|
+
class_attribute :enums
|
110
|
+
def self.enum hash
|
111
|
+
key = hash.keys.first
|
112
|
+
(self.enums ||= {}).merge! hash
|
113
|
+
define_attribute_methods if !attribute_methods_generated?
|
114
|
+
class_eval %{
|
115
|
+
def #{key}
|
116
|
+
missing_attribute('#{key}', caller) unless @attributes.has_key?('#{key}')
|
117
|
+
self.class.enums[:#{key}][@attributes['#{key}']]
|
118
|
+
end
|
119
|
+
def #{key}=(val)
|
120
|
+
write_attribute('#{key}', Fixnum === val ? val : self.class.enums[:#{key}].index val.to_s
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
# fix for thinking_sphinx equation in #instances_from_class:
|
126
|
+
# ids.collect {|obj_id| instances.detect do |obj| obj.primary_key_for_sphinx == obj_id end}
|
127
|
+
# where obj_id is Array
|
128
|
+
def primary_key_for_sphinx
|
129
|
+
[read_attribute(self.class.primary_key_for_sphinx)]
|
130
|
+
end
|
131
|
+
|
92
132
|
end
|
93
133
|
|
94
134
|
class Relation
|
@@ -6,8 +6,16 @@ class BlackHole
|
|
6
6
|
# => #<BlackHole:0xb66367b0>
|
7
7
|
#
|
8
8
|
# Think twice before use it. It may devour your code!
|
9
|
-
def method_missing(*)
|
10
|
-
|
9
|
+
def method_missing(m, *args)
|
10
|
+
case m.to_s[-1,1]
|
11
|
+
when '?'; false
|
12
|
+
when '!'; nil
|
13
|
+
when '='; args.first
|
14
|
+
else self
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
18
|
+
if RUBY_VERSION < '1.9'
|
19
|
+
undef id
|
20
|
+
end
|
13
21
|
end
|
@@ -240,7 +240,7 @@ module RMTools
|
|
240
240
|
self.class.__send__(:include, instructions_module)
|
241
241
|
@Instructions = init_instructions
|
242
242
|
@MainParseRE = MainParseRE
|
243
|
-
add_method_seeker('.get_opts') {|s, args| $log
|
243
|
+
add_method_seeker('.get_opts') {|s, args| $log <= args}
|
244
244
|
end
|
245
245
|
|
246
246
|
def add_instruction(re, &callback)
|
@@ -254,7 +254,7 @@ module RMTools
|
|
254
254
|
else
|
255
255
|
pattern = /(?:^|[\s#{Leftop}])(#{name})([(`"' ] *|:['"]?)/
|
256
256
|
end
|
257
|
-
$log
|
257
|
+
$log <= pattern
|
258
258
|
add_instruction(pattern) {|s, m|
|
259
259
|
$log << m
|
260
260
|
yield s, arguments(s, m)
|
data/lib/rmtools/dev/logging.rb
CHANGED
@@ -44,20 +44,34 @@ module RMTools
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def defaults
|
47
|
-
puts %{
|
47
|
+
puts %{ #common options:
|
48
|
+
:q => false, # not print
|
48
49
|
:out => false, # output to file, may contain strftime's %H%M%Y etc for filename
|
49
|
-
:color_out => false # do not clean control characters that make output to file colorful (set to true makes more readable out of tail -n/-f but hardly readable file as text by gui)
|
50
50
|
:time => ["%H:%M:%S", "%03d"], # strftime, [msecs]
|
51
|
-
:
|
52
|
-
|
51
|
+
:type => :console, # or :html
|
52
|
+
#console values:
|
53
|
+
:caller => "#{@c.gray('%f:%l')} #{@c.red_bold(':%m')}", # "file:line :method", %p is for fullpath
|
54
|
+
:format => "%time %mode [%caller]: %text" # format of entire log string, %mode is {#{%w(debug log info warn).map {|i| @highlight[i.to_sym]}*', '}}
|
55
|
+
:color_out => false # do not clean control characters that make output to file colorful; set to true makes more readable output of `tail' but hardly readable by gui file output
|
56
|
+
#html options:
|
57
|
+
:caller => "<a class='l'>%f:%l</a> <a class='m'>:%m</a>",
|
58
|
+
:format => "<div class='line'><a class='t'>%time</a> <a class='%mode'>%mode</m> [%caller]: <p>%text</p>%att</div>", # %att is for array of objects that should be formatted by the next option
|
59
|
+
:att =>"<div class='att'><div class='hide'>+</div><pre>%s</pre></div>", # .hide should be scripted to work like a spoiler
|
60
|
+
:serializer => RMTools::RMLogger::HTML # should respond to :render(obj); nil value means each object will be just #inspect'ed}
|
53
61
|
end
|
54
62
|
|
55
63
|
# set any needed params, the rest will be set by default
|
56
64
|
def set_format *args
|
57
|
-
global, format = args.fetch_opts [nil],
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
global, format = args.fetch_opts [nil], :type => :console, :time => ["%H:%M:%S", "%03d"]
|
66
|
+
format = if format[:type] == :html; {
|
67
|
+
:caller => "<a class='l'>%f:%l</a> <a class='m'>:%m</a>",
|
68
|
+
:format => "<div class='line'><a class='t'>%time</a> <a class='%mode'>%mode</m> [%caller]: <p>%text</p>%att</div>",
|
69
|
+
:att =>"<div class='att'><div class='hide'>+</div><pre>%s</pre></div>",
|
70
|
+
:serializer => RMTools::RMLogger::HTML
|
71
|
+
}; else {
|
72
|
+
:caller => "#{@c.gray('%f:%l')} #{@c.red_bold(':%m')}",
|
73
|
+
:format => "%time %mode [%caller]: %text"
|
74
|
+
} end.merge format
|
61
75
|
if global
|
62
76
|
_set_format @default_format, format
|
63
77
|
else
|
@@ -76,27 +90,27 @@ module RMTools
|
|
76
90
|
log_ = opts&NOLOG==0
|
77
91
|
print_ = opts&NOPRINT==0
|
78
92
|
str = cfg.fmt.dup
|
79
|
-
str.
|
93
|
+
str.gsub! "%mode", @highlight[mode]
|
80
94
|
if bind
|
81
95
|
text = bind.report text
|
82
96
|
elsif !text.is String
|
83
97
|
text = text.inspect
|
84
98
|
end
|
85
|
-
str.sub! "%text", text
|
86
|
-
str << "\n" if opts&INLINE==0
|
87
99
|
out = cfg.out
|
88
100
|
if cfg._time or cfg.path_format
|
89
101
|
now = Time.now
|
90
102
|
if cfg._time
|
91
103
|
time = now.strftime cfg.tf[0]
|
92
104
|
time << ".#{cfg.tf[1]%[now.usec/1000]}" if cfg.tf[1]
|
93
|
-
str.
|
105
|
+
str.gsub! "%time", time
|
94
106
|
end
|
95
107
|
out = now.strftime cfg.out if cfg.path_format
|
96
108
|
end
|
97
109
|
if caler
|
98
|
-
str.
|
110
|
+
str.gsub! "%caller", caler.sub(String::CALLER_RE, cfg.cf)
|
99
111
|
end
|
112
|
+
str.gsub! "%text", text
|
113
|
+
str << "\n" if opts&INLINE==0
|
100
114
|
log_str = cfg.color_out ? str : @c.clean(str)
|
101
115
|
RMTools.write out, log_str if log_
|
102
116
|
Kernel.print str if print_
|
data/lib/rmtools/dev/timer.rb
CHANGED
@@ -7,13 +7,17 @@ module RMTools
|
|
7
7
|
quiet, mute_warn = $quiet, $log.mute_warn
|
8
8
|
$quiet = $log.mute_warn = true
|
9
9
|
t1 = Time.now
|
10
|
-
timez.times {yield}
|
10
|
+
timez.times {yield} if timez > 0
|
11
11
|
res = yield
|
12
|
-
t2 =
|
13
|
-
|
12
|
+
t2 = Time.now
|
13
|
+
ts.times {}
|
14
|
+
t3 = Time.now.to_f*1000
|
15
|
+
t2 = t2.to_f*1000
|
16
|
+
t1 = t1.to_f*1000
|
17
|
+
delta = (t2 - t1 - (t3 - t2)).round.to_f
|
14
18
|
$quiet, $log.mute_warn = quiet, mute_warn
|
15
19
|
res = res.inspect
|
16
|
-
puts "#{output ? "res: #{res.size > 1000 ? res[0...
|
20
|
+
puts "#{output ? "res: #{res.size > 1000 ? res[0...999]+"…" : res}\n" : "size of res string: #{res.to_s.size}, "}one: #{Painter.gray '%0.4fms'%[delta/ts]}, total: #{Painter.gray "#{delta}ms"}"
|
17
21
|
end
|
18
22
|
|
19
23
|
module_function :timer
|
@@ -3,6 +3,64 @@ require 'active_support/core_ext/array'
|
|
3
3
|
RMTools::require 'functional/fold'
|
4
4
|
|
5
5
|
class Array
|
6
|
+
# core methods overwrite
|
7
|
+
# sometimes we cannot afford do zillions of cycles just for ensure A | [] = A - [] = A or A & [] = []
|
8
|
+
# though - and & should be improved within C-extension to break loop when no items have lost in self
|
9
|
+
alias union |
|
10
|
+
alias induction +
|
11
|
+
alias subtraction -
|
12
|
+
alias intersection &
|
13
|
+
private :union, :induction, :subtraction, :intersection
|
14
|
+
|
15
|
+
def |(ary)
|
16
|
+
if empty?
|
17
|
+
ary.uniq
|
18
|
+
elsif ary.respond_to?:empty? and ary.empty?
|
19
|
+
dup
|
20
|
+
else union(ary)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def +(ary)
|
25
|
+
if empty?
|
26
|
+
if ary.respond_to?:empty? and ary.empty?
|
27
|
+
[]
|
28
|
+
else ary.dup
|
29
|
+
end
|
30
|
+
elsif ary.respond_to?:empty? and ary.empty?
|
31
|
+
dup
|
32
|
+
else induction(ary)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def -(ary)
|
37
|
+
if empty?
|
38
|
+
[]
|
39
|
+
elsif ary.respond_to?:empty? and ary.empty?
|
40
|
+
dup
|
41
|
+
else subtraction(ary)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def &(ary)
|
46
|
+
if empty? or (ary.respond_to?:empty? and ary.empty?)
|
47
|
+
[]
|
48
|
+
else intersection(ary)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def ^(ary)
|
53
|
+
if empty? or (ary.respond_to? :empty? and ary.empty?)
|
54
|
+
[dup, ary.dup]
|
55
|
+
elsif self == ary
|
56
|
+
[[], []]
|
57
|
+
else
|
58
|
+
common = intersection ary
|
59
|
+
[self - common, ary - common]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
alias diff ^
|
6
64
|
|
7
65
|
# arithmetics
|
8
66
|
def avg
|
@@ -97,6 +155,10 @@ class Array
|
|
97
155
|
find {|e| e.__send__(key) == value}
|
98
156
|
end
|
99
157
|
|
158
|
+
def select_by(key, value)
|
159
|
+
select {|e| e.__send__(key) == value}
|
160
|
+
end
|
161
|
+
|
100
162
|
# concatenation
|
101
163
|
# analogue to String#>>
|
102
164
|
def >>(ary)
|
@@ -139,7 +201,7 @@ class Array
|
|
139
201
|
def sum(identity=0, &b) foldl(:+, &b) || identity end
|
140
202
|
|
141
203
|
# fastering activesupport's method
|
142
|
-
def group_by(&b)
|
204
|
+
def group_by(&b) arrange(:group, &b) end
|
143
205
|
|
144
206
|
|
145
207
|
|
@@ -14,14 +14,16 @@ unless defined? RMTools::Iterators
|
|
14
14
|
# => [[1, 2, 3], [3, 4, 6]]
|
15
15
|
class Array
|
16
16
|
alias :throw_no :method_missing
|
17
|
-
RMTools::Iterators = %r{^(#{(
|
17
|
+
RMTools::Iterators = %r{^(#{(instance_methods.grep(/_by$/)+%w{every no select reject partition find_all find sum foldr find_by select_by})*'|'})_([\w\d\_]+[!?]?)}
|
18
18
|
|
19
19
|
def method_missing(method, *args, &block)
|
20
20
|
if match = (meth = method.to_s).match(RMTools::Iterators)
|
21
21
|
iterator, meth = match[1].to_sym, match[2].to_sym
|
22
22
|
begin
|
23
|
-
|
24
|
-
|
23
|
+
case iterator
|
24
|
+
when :every then iterator = :every?
|
25
|
+
when :no then iterator = :no?
|
26
|
+
end
|
25
27
|
return case iterator
|
26
28
|
when :sum; sum(args.shift) {|i| i.__send__ meth, *args, &block}
|
27
29
|
when :find_by; find_by(meth, *args)
|
@@ -28,6 +28,11 @@ class Range
|
|
28
28
|
self & -range
|
29
29
|
end
|
30
30
|
|
31
|
+
def ^(range)
|
32
|
+
common = self & range
|
33
|
+
self - common | range - common
|
34
|
+
end
|
35
|
+
|
31
36
|
def x?(range)
|
32
37
|
range_end = range.include_end.end
|
33
38
|
self_end = self.include_end.end
|
@@ -169,6 +174,11 @@ class XRange
|
|
169
174
|
self & -range
|
170
175
|
end
|
171
176
|
|
177
|
+
def ^(range)
|
178
|
+
common = self & range
|
179
|
+
self - common | range - common
|
180
|
+
end
|
181
|
+
|
172
182
|
private
|
173
183
|
|
174
184
|
def intersect(range)
|
@@ -196,7 +206,7 @@ public
|
|
196
206
|
end
|
197
207
|
|
198
208
|
def include?(number_or_range)
|
199
|
-
@ranges.
|
209
|
+
@ranges.find {|r| r.include?(number_or_range)}
|
200
210
|
end
|
201
211
|
|
202
212
|
def begin
|
data/lib/rmtools/fs/file.rb
CHANGED
@@ -2,16 +2,60 @@
|
|
2
2
|
RMTools::require 'fs/io'
|
3
3
|
|
4
4
|
class File
|
5
|
+
PathMemo = {} if !defined? PathMemo
|
5
6
|
|
6
7
|
def inspect
|
7
8
|
"<#File \"#{path}\" #{closed? ? 'closed' : stat.size.bytes}>"
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def real_path path, memo=1
|
14
|
+
a = expand_path(path).split(/[\/\\]/)
|
15
|
+
a.each_index {|i|
|
16
|
+
if a[j=-(i+1)]['~']
|
17
|
+
n = i+2>a.size ? a[j] : join(a[0..-(i+2)], a[j])
|
18
|
+
a[j] = PathMemo[n] || real_name(n)
|
19
|
+
PathMemo[n] = a[j] if memo
|
20
|
+
else break
|
21
|
+
end
|
22
|
+
}
|
23
|
+
a*'/'
|
24
|
+
end
|
25
|
+
|
26
|
+
def real_name(df)
|
27
|
+
if file?(df)
|
28
|
+
new(df).real_name
|
29
|
+
elsif directory?(df)
|
30
|
+
Dir.new(df).real_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def modify(pattern, bak=true, &block)
|
35
|
+
Dir[pattern].select {|file| __modify(file, bak, &block)}
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def include?(name, str)
|
40
|
+
f = new name, 'r'
|
41
|
+
incl = f.include? str
|
42
|
+
f.close
|
43
|
+
incl
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def __modify(file, bak=true)
|
48
|
+
if orig_text = read(file)
|
49
|
+
copy_text = orig_text.dup
|
50
|
+
res_text = yield copy_text
|
51
|
+
# res may be nil in case of gsub!
|
52
|
+
# though copy_text wouldn't be equal orig_text if something has been changed
|
53
|
+
if orig_text != res_text and (res_text or orig_text != copy_text)
|
54
|
+
rename file, file+'.bak' if bak
|
55
|
+
RMTools.rw(file, res_text.is(String) ? res_text : copy_text)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
15
59
|
end
|
16
60
|
|
17
61
|
def include?(str)
|
@@ -39,13 +83,6 @@ class File
|
|
39
83
|
File.new(path,'r')
|
40
84
|
end
|
41
85
|
|
42
|
-
def self.modify(file, bak=true)
|
43
|
-
orig_text = read file
|
44
|
-
text = yield orig_text
|
45
|
-
rename file, file+'.bak' if bak
|
46
|
-
RMTools.rw(file, text.is(String) ? text : orig_text)
|
47
|
-
end
|
48
|
-
|
49
86
|
def cp(df)
|
50
87
|
dir = File.dirname df
|
51
88
|
FileUtils.mkpath dir unless File.directory? dir
|
@@ -70,7 +107,7 @@ class File
|
|
70
107
|
pc.reject! {|f| !f[re]}
|
71
108
|
end
|
72
109
|
if defined? Amatch
|
73
|
-
count = [:hamming_similar, :levenshtein_similar, :jaro_similar].sum {|m| pc.group_by {|f| (ext ? f[0..-(ext.size+2)] : f).upcase.ljust(ms).send(m, n)}.max[1]}.
|
110
|
+
count = [:hamming_similar, :levenshtein_similar, :jaro_similar].sum {|m| pc.group_by {|f| (ext ? f[0..-(ext.size+2)] : f).upcase.ljust(ms).send(m, n)}.max[1]}.arrange.to_a
|
74
111
|
max = count.lasts.max
|
75
112
|
res = count.find {|c|
|
76
113
|
c[1] == max and File.file?(df=File.join(pp, c[0])) and File.stat(df) == ss
|
@@ -82,26 +119,4 @@ class File
|
|
82
119
|
}
|
83
120
|
end
|
84
121
|
|
85
|
-
PathMemo = {} if !defined? PathMemo
|
86
|
-
def self.real_path path, memo=1
|
87
|
-
a = expand_path(path).split(/[\/\\]/)
|
88
|
-
a.each_index {|i|
|
89
|
-
if a[j=-(i+1)]['~']
|
90
|
-
n = i+2>a.size ? a[j] : join(a[0..-(i+2)], a[j])
|
91
|
-
a[j] = PathMemo[n] || real_name(n)
|
92
|
-
PathMemo[n] = a[j] if memo
|
93
|
-
else break
|
94
|
-
end
|
95
|
-
}
|
96
|
-
a*'/'
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.real_name(df)
|
100
|
-
if file?(df)
|
101
|
-
new(df).real_name
|
102
|
-
elsif directory?(df)
|
103
|
-
Dir.new(df).real_name
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
122
|
end
|
data/lib/rmtools/fs/io.rb
CHANGED
@@ -64,13 +64,13 @@ module RMTools
|
|
64
64
|
if file = dest.find {|f| File.file?(f.tr '\\', '/')}
|
65
65
|
File.open(file.tr('\\', '/'), File::RDONLY) {|f| f.read}
|
66
66
|
else
|
67
|
-
warn "couldn't read from neither #{dest[0].inspect} nor #{dest[1..-1].inspects*' nor '}; files missed (called from #{caller[
|
67
|
+
warn "couldn't read from neither #{dest[0].inspect} nor #{dest[1..-1].inspects*' nor '}; files missed (called from #{caller[2]})"
|
68
68
|
end
|
69
69
|
else
|
70
70
|
if File.file? dest.tr('\\', '/')
|
71
71
|
File.open(dest.tr('\\', '/'), File::RDONLY) {|f| f.read}
|
72
72
|
else
|
73
|
-
warn "couldn't read from #{dest.inspect}; file missed (called from #{caller[
|
73
|
+
warn "couldn't read from #{dest.inspect}; file missed (called from #{caller[2]})"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
}
|
data/lib/rmtools/install.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require File.expand_path('require', File.dirname(__FILE__))
|
3
3
|
RMTools::require 'fs'
|
4
|
-
require 'digest/md5'
|
5
4
|
|
6
|
-
def ext_files_not_modified(ext_name
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
!
|
12
|
-
|
13
|
-
}
|
5
|
+
def ext_files_not_modified(ext_name, version)
|
6
|
+
spec = Gem::Specification.find_all_by_name(ext_name).find {|s| s.version.version == version}
|
7
|
+
return unless spec
|
8
|
+
path = spec.full_gem_path
|
9
|
+
!spec.files.grep(/^ext\//).find {|f|
|
10
|
+
!(File.file?(installed=File.join(path, f)) and IO.read(f) == IO.read(installed))
|
11
|
+
}
|
14
12
|
end
|
15
13
|
|
16
14
|
def compile_manifest(exc=%w(pkg))
|
17
|
-
|
18
|
-
|
15
|
+
fs = Dir.new('.').recursive_content
|
16
|
+
RMTools.rw 'Manifest.txt', (exc ? fs.reject {|i| i[/^(#{exc*'|'})\//]} : fs)*"\n"
|
19
17
|
end
|
data/lib/rmtools/lang/ansi.rb
CHANGED
@@ -1,18 +1,41 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'iconv'
|
3
|
+
# Although ruby >= 1.9.3 would complain about not using String#encode, iconv is 2-4 times faster and still handles the ruby string encoding
|
3
4
|
|
4
5
|
module RMTools
|
5
6
|
ANSI2UTF = Iconv.new("UTF-8", "WINDOWS-1251").method :iconv
|
6
7
|
UTF2ANSI = Iconv.new("WINDOWS-1251", "UTF-8").method :iconv
|
7
|
-
|
8
|
+
|
8
9
|
module Cyrillic
|
9
10
|
RU_LETTERS = "абвгдеёжзийклмнопрстуфхцчшщьыъэюя", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ"
|
10
11
|
|
11
|
-
if RUBY_VERSION
|
12
|
+
if RUBY_VERSION > '1.9'
|
12
13
|
ANSI_LETTERS_UC = ["\270\340-\377", "\250\300-\337"].force_encodings "Windows-1251"
|
13
14
|
ANSI_LETTERS_DC = ANSI_LETTERS_UC.reverse
|
14
15
|
ANSI_YOYE = ["\270\250", "\345\305"].force_encodings "Windows-1251"
|
15
16
|
ANSI_ENCODING = ANSI_LETTERS_UC[0].encoding
|
16
17
|
end
|
17
18
|
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class String
|
23
|
+
|
24
|
+
# Actually, for short strings and 1251<->65001 it's much faster to use predefined ANSI2UTF and UTF2ANSI procs
|
25
|
+
def utf(from_encoding='WINDOWS-1251')
|
26
|
+
Iconv.new('UTF-8', from_encoding).iconv(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def ansi(from_encoding='UTF-8')
|
30
|
+
Iconv.new('WINDOWS-1251', from_encoding).iconv(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def utf!(from_encoding='WINDOWS-1251')
|
34
|
+
replace utf from_encoding
|
35
|
+
end
|
36
|
+
|
37
|
+
def ansi!(from_encoding='UTF-8')
|
38
|
+
replace ansi from_encoding
|
39
|
+
end
|
40
|
+
|
18
41
|
end
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
RMTools::require 'lang/
|
2
|
+
RMTools::require 'lang/ansi'
|
3
3
|
|
4
4
|
class String
|
5
5
|
include RMTools::Cyrillic
|
6
|
-
|
7
|
-
def cyr_ic
|
8
|
-
gsub(/[ёЁ]/, '[ёЁ]').gsub(/[йЙ]/, '[йЙ]').gsub(/[цЦ]/, '[цЦ]').gsub(/[уУ]/, '[уУ]').gsub(/[кК]/, '[кК]').gsub(/[еЕ]/, '[еЕ]').gsub(/[нН]/, '[нН]').gsub(/[гГ]/, '[гГ]').gsub(/[шШ]/, '[шШ]').gsub(/[щЩ]/, '[щЩ]').gsub(/[зЗ]/, '[зЗ]').gsub(/[хХ]/, '[хХ]').gsub(/[ъЪ]/, '[ъЪ]').gsub(/[фФ]/, '[фФ]').gsub(/[ыЫ]/, '[ыЫ]').gsub(/[вВ]/, '[вВ]').gsub(/[аА]/, '[аА]').gsub(/[пП]/, '[пП]').gsub(/[рР]/, '[рР]').gsub(/[оО]/, '[оО]').gsub(/[лЛ]/, '[лЛ]').gsub(/[дД]/, '[дД]').gsub(/[жЖ]/, '[жЖ]').gsub(/[эЭ]/, '[эЭ]').gsub(/[яЯ]/, '[яЯ]').gsub(/[чЧ]/, '[чЧ]').gsub(/[сС]/, '[сС]').gsub(/[мМ]/, '[мМ]').gsub(/[иИ]/, '[иИ]').gsub(/[тТ]/, '[тТ]').gsub(/[ьЬ]/, '[ьЬ]').gsub(/[бБ]/, '[бБ]').gsub(/[юЮ]/, '[юЮ]')
|
9
|
-
end
|
10
|
-
alias :ci :cyr_ic
|
11
6
|
|
12
7
|
def translit
|
13
8
|
gsub(/[ёЁ]/, 'yo').gsub(/[йЙ]/, 'y').gsub(/[цЦ]/, 'c').gsub(/[уУ]/, 'u').gsub(/[кК]/, 'k').gsub(/[еЕ]/, 'e').gsub(/[нН]/, 'n').gsub(/[гГ]/, 'g').gsub(/[шШ]/, 'sh').gsub(/[щЩ]/, 'sch').gsub(/[зЗ]/, 'z').gsub(/[хХ]/, 'h').gsub(/[ьЬъЪ]/, "'").gsub(/[фФ]/, 'f').gsub(/[иИыЫ]/, 'i').gsub(/[вВ]/, 'v').gsub(/[аА]/, 'a').gsub(/[пП]/, 'p').gsub(/[рР]/, 'r').gsub(/[оО]/, 'o').gsub(/[лЛ]/, 'l').gsub(/[дД]/, 'd').gsub(/[жЖ]/, 'j').gsub(/[эЭ]/, 'e').gsub(/[яЯ]/, 'ya').gsub(/[чЧ]/, 'ch').gsub(/[сС]/, 's').gsub(/[мМ]/, 'm').gsub(/[тТ]/, 't').gsub(/[бБ]/, 'b').gsub(/[юЮ]/, 'yu')
|
@@ -26,11 +21,7 @@ class String
|
|
26
21
|
self !~ /[^А-пр-ёЁ]/
|
27
22
|
end
|
28
23
|
|
29
|
-
|
30
|
-
ANSI2UTF[UTF2ANSI[self].squeeze]
|
31
|
-
end
|
32
|
-
|
33
|
-
if RUBY_VERSION >= "1.9"
|
24
|
+
if RUBY_VERSION > "1.9"
|
34
25
|
|
35
26
|
def ru2en
|
36
27
|
tr "ёйцукенгшщзхъфывапролдэячсмить/.ю?,б\"№;:жЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИВТЬБЮ", "`qwertyuiop[]asdfghjkl'zxcvbnm|/.&?,@\#$^;~QWERTYUIOP{}ASDFGHJKL:\"ZXCVBDNM<>"
|
@@ -52,10 +43,6 @@ class String
|
|
52
43
|
tr(*ANSI_LETTERS_DC)
|
53
44
|
end
|
54
45
|
|
55
|
-
def ccap
|
56
|
-
self[0].cupcase + self[1..-1]
|
57
|
-
end
|
58
|
-
|
59
46
|
def cuncap
|
60
47
|
self[0].cdowncase + self[1..-1]
|
61
48
|
end
|
@@ -66,10 +53,14 @@ class String
|
|
66
53
|
tr(*ANSI_YOYE)
|
67
54
|
end
|
68
55
|
|
69
|
-
alias csize size
|
70
|
-
alias cljust ljust
|
71
|
-
alias cjust
|
72
|
-
alias ccenter center
|
56
|
+
alias csize size
|
57
|
+
alias cljust ljust
|
58
|
+
alias cjust rjust
|
59
|
+
alias ccenter center
|
60
|
+
alias ccap capitalize
|
61
|
+
alias csqueeze squeeze
|
62
|
+
|
63
|
+
def ci; self end
|
73
64
|
else
|
74
65
|
|
75
66
|
def csize
|
@@ -80,8 +71,8 @@ class String
|
|
80
71
|
ANSI2UTF[UTF2ANSI[self].ljust(*args)]
|
81
72
|
end
|
82
73
|
|
83
|
-
def
|
84
|
-
ANSI2UTF[UTF2ANSI[self].
|
74
|
+
def crjust(*args)
|
75
|
+
ANSI2UTF[UTF2ANSI[self].rjust(*args)]
|
85
76
|
end
|
86
77
|
|
87
78
|
def ccenter(*args)
|
@@ -108,6 +99,10 @@ class String
|
|
108
99
|
self[0,2].cdowncase(encode) + self[2..-1]
|
109
100
|
end
|
110
101
|
|
102
|
+
def csqueeze
|
103
|
+
ANSI2UTF[UTF2ANSI[self].squeeze]
|
104
|
+
end
|
105
|
+
|
111
106
|
def rmumlaut(encode=1)
|
112
107
|
encode ?
|
113
108
|
ANSI2UTF[UTF2ANSI[self].tr("\270\250", "\345\305")]:
|
@@ -121,6 +116,10 @@ class String
|
|
121
116
|
def en2ru
|
122
117
|
gsub("`", "ё").gsub("q", "й").gsub("w", "ц").gsub("e", "у").gsub("r", "к").gsub("t", "е").gsub("y", "н").gsub("u", "г").gsub("i", "ш").gsub("o", "щ").gsub("p", "з").gsub("[", "х").gsub("]", "ъ").gsub("a", "ф").gsub("s", "ы").gsub("d", "в").gsub("f", "а").gsub("g", "п").gsub("h", "р").gsub("j", "о").gsub("k", "л").gsub("l", "д").gsub(";", "ж").gsub(":", "Ж").gsub("'", "э").gsub("z", "я").gsub("x", "ч").gsub("c", "с").gsub("v", "м").gsub("b", "и").gsub("n", "т").gsub("m", "ь").gsub(",", "б").gsub(".", "ю").gsub("/", ".").gsub("|", "/").gsub("?", ",").gsub("\"", "Э").gsub("@", "\"").gsub("#", "№").gsub("$", ";").gsub("^", ":").gsub("&", "?").gsub("~", "Ё").gsub("Q", "Й").gsub("W", "Ц").gsub("E", "У").gsub("R", "К").gsub("T", "Е").gsub("Y", "Н").gsub("U", "Г").gsub("I", "Ш").gsub("O", "Щ").gsub("P", "З").gsub("{", "Х").gsub("}", "Ъ").gsub("A", "Ф").gsub("S", "Ы").gsub("D", "В").gsub("F", "А").gsub("G", "П").gsub("H", "Р").gsub("J", "О").gsub("K", "Л").gsub("L", "Д").gsub("Z", "Я").gsub("X", "Ч").gsub("C", "С").gsub("V", "М").gsub("B", "И").gsub("N", "Т").gsub("M", "Ь").gsub("<", "Б").gsub(">", "Ю")
|
123
118
|
end
|
119
|
+
|
120
|
+
def ci
|
121
|
+
gsub(/[ёЁ]/, '[ёЁ]').gsub(/[йЙ]/, '[йЙ]').gsub(/[цЦ]/, '[цЦ]').gsub(/[уУ]/, '[уУ]').gsub(/[кК]/, '[кК]').gsub(/[еЕ]/, '[еЕ]').gsub(/[нН]/, '[нН]').gsub(/[гГ]/, '[гГ]').gsub(/[шШ]/, '[шШ]').gsub(/[щЩ]/, '[щЩ]').gsub(/[зЗ]/, '[зЗ]').gsub(/[хХ]/, '[хХ]').gsub(/[ъЪ]/, '[ъЪ]').gsub(/[фФ]/, '[фФ]').gsub(/[ыЫ]/, '[ыЫ]').gsub(/[вВ]/, '[вВ]').gsub(/[аА]/, '[аА]').gsub(/[пП]/, '[пП]').gsub(/[рР]/, '[рР]').gsub(/[оО]/, '[оО]').gsub(/[лЛ]/, '[лЛ]').gsub(/[дД]/, '[дД]').gsub(/[жЖ]/, '[жЖ]').gsub(/[эЭ]/, '[эЭ]').gsub(/[яЯ]/, '[яЯ]').gsub(/[чЧ]/, '[чЧ]').gsub(/[сС]/, '[сС]').gsub(/[мМ]/, '[мМ]').gsub(/[иИ]/, '[иИ]').gsub(/[тТ]/, '[тТ]').gsub(/[ьЬ]/, '[ьЬ]').gsub(/[бБ]/, '[бБ]').gsub(/[юЮ]/, '[юЮ]')
|
122
|
+
end
|
124
123
|
|
125
124
|
end
|
126
125
|
|
data/lib/rmtools/lang/regexp.rb
CHANGED
data/lib/rmtools/text/regexp.rb
CHANGED
@@ -11,7 +11,7 @@ class Regexp
|
|
11
11
|
bs = klass = count = nil
|
12
12
|
group_marks = []
|
13
13
|
oppose = {'('=>')', ')'=>'(', '^'=>'$', '$'=>'^'}
|
14
|
-
borders = {'Z'=>'\A', 'A'=>'\Z'}
|
14
|
+
borders = {'Z'=>'\A', 'A'=>'\Z', 'z'=>'\a', 'a'=>'\z'}
|
15
15
|
ext = options&2 != 0
|
16
16
|
StringScanner(source).each(/./) {|s|
|
17
17
|
if (m = s.matched) == '\\'
|
@@ -79,5 +79,14 @@ class String
|
|
79
79
|
#end
|
80
80
|
#
|
81
81
|
# this method defined in Enumerable and returns Enumerable::Enumerator that should be converted to array of integers, not hex-strings
|
82
|
+
if RUBY_VERSION < '1.9'
|
83
|
+
def symbols_count
|
84
|
+
unpack('U*').size
|
85
|
+
end
|
86
|
+
else
|
87
|
+
def symbols_count
|
88
|
+
size
|
89
|
+
end
|
90
|
+
end
|
82
91
|
|
83
92
|
end
|
@@ -59,7 +59,7 @@ class String
|
|
59
59
|
private
|
60
60
|
def split_by_syntax(str, maxlen, buflen=0)
|
61
61
|
len, add = maxlen - buflen, nil
|
62
|
-
[/[
|
62
|
+
[/[^.?!…]+\z/, /[^;]+\z/, /[^,:]+\z/, /[^\n]+/, /\S+\z/, /[^。、]+z/].each {|t|
|
63
63
|
if !(add = str[t]) or add.size <= len
|
64
64
|
return add
|
65
65
|
end
|
@@ -116,13 +116,31 @@ class String
|
|
116
116
|
|
117
117
|
# 'An elegant way to factor duplication out of options passed to a series of method calls. Each method called in the block, with the block variable as the receiver, will have its options merged with the default options hash provided. '.cut_line 100
|
118
118
|
# => "An elegant way to factor duplication out of options passed to a series of method calls..."
|
119
|
+
if RUBY_VERSION < '1.9'
|
119
120
|
def cut_line(maxlen, *opts)
|
120
121
|
terminator, opts = opts.fetch_opts [:syntax, :flags]
|
121
|
-
opts[:charsize] ||=
|
122
|
+
opts[:charsize] ||= cyr? ? 2 : 1
|
122
123
|
return self if size <= maxlen
|
123
|
-
maxlen
|
124
|
-
|
124
|
+
blocks = split_to_blocks(maxlen*opts[:charsize]-3, terminator, :strips => true, :strict_overhead => false, :lines => 1)
|
125
|
+
cuted = (blocks[0] || self)[0, maxlen]
|
126
|
+
if terminator == :syntax
|
127
|
+
cuted.gsub!(/[.!?,;]$/, '')
|
128
|
+
else cuted.chomp!('.')
|
129
|
+
end
|
130
|
+
cuted + '…'
|
131
|
+
end
|
132
|
+
else
|
133
|
+
def cut_line(maxlen, terminator=:syntax)
|
134
|
+
return self if size <= maxlen
|
135
|
+
blocks = split_to_blocks(maxlen-1, terminator, :strips => true, :strict_overhead => false, :lines => 1)
|
136
|
+
cuted = (blocks[0] || self)[0, maxlen]
|
137
|
+
if terminator == :syntax
|
138
|
+
cuted.gsub!(/[.!?,;]$/, '')
|
139
|
+
else cuted.chomp!('.')
|
140
|
+
end
|
141
|
+
cuted + '…'
|
125
142
|
end
|
143
|
+
end
|
126
144
|
|
127
145
|
# puts 'An elegant way to factor duplication out of options passed to a series of method calls. Each method called in the block, with the block variable as the receiver, will have its options merged with the default options hash provided. '.split_to_lines 50
|
128
146
|
# produces:
|
@@ -134,12 +152,19 @@ class String
|
|
134
152
|
#
|
135
153
|
# This method is use cyrillic lib only to detect char byte-length
|
136
154
|
# options: charsize, no_blanks, strips
|
155
|
+
if RUBY_VERSION < '1.9'
|
156
|
+
def split_to_lines(maxlen, *opts)
|
157
|
+
raise Exception, "Can't break text with maxlen = #{maxlen}" if maxlen < 1
|
158
|
+
opts = opts.fetch_opts([:flags], :strips => true).merge(:strict_overhead => false)
|
159
|
+
opts[:charsize] ||= a[0].cyr? ? 2 : 1
|
160
|
+
split("\n").map {|string| string.strip.split_to_blocks(maxlen*opts[:charsize], opts)}.flatten*"\n"
|
161
|
+
end
|
162
|
+
else
|
137
163
|
def split_to_lines(maxlen, *opts)
|
138
164
|
raise Exception, "Can't break text with maxlen = #{maxlen}" if maxlen < 1
|
139
|
-
opts = opts.fetch_opts
|
140
|
-
|
141
|
-
opts[:charsize] ||= RUBY_VERSION < '1.9' && a[0].cyr? ? 2 : 1
|
142
|
-
a.map {|string| string.strip.split_to_blocks(maxlen*opts[:charsize], opts.merge(:strict_overhead => false))}.flatten*"\n"
|
165
|
+
opts = opts.fetch_opts([:flags], :strips => true).merge(:strict_overhead => false)
|
166
|
+
split("\n").map {|string| string.strip.split_to_blocks(maxlen, opts)}.flatten*"\n"
|
143
167
|
end
|
168
|
+
end
|
144
169
|
|
145
170
|
end
|
data/lib/rmtools/xml/string.rb
CHANGED
data/lib/rmtools/xml/xpath.rb
CHANGED
@@ -11,6 +11,8 @@ module LibXML
|
|
11
11
|
raise XML::Error, "can't process '#{$1}' operator"
|
12
12
|
end
|
13
13
|
x = xpath.dup
|
14
|
+
x.gsub! %r{([^\\])\s*>\s*}, '\1/'
|
15
|
+
x.gsub! %r{([^\\])\s+}, '\1//'
|
14
16
|
x.gsub! %r{\.([\w-]+)([\[\{/]|\Z)}, '[@class="\1"]\2'
|
15
17
|
x.gsub! %r{#([\w-]+)([\[\{/]|\Z)}, '[@id="\1"]\2'
|
16
18
|
x.gsub! %r{(^|/)([^.#\w*/'"])}, '\1*\2'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rmtools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
9
|
+
- 7
|
10
|
+
version: 1.2.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Shinku
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
19
|
-
default_executable:
|
18
|
+
date: 2012-05-18 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rake
|
@@ -65,7 +64,7 @@ dependencies:
|
|
65
64
|
version: "2.12"
|
66
65
|
type: :development
|
67
66
|
version_requirements: *id003
|
68
|
-
description: Applied
|
67
|
+
description: Applied library primarily for debug and text/arrays/files processing purposes.
|
69
68
|
email:
|
70
69
|
- tinbka@gmail.com
|
71
70
|
executables: []
|
@@ -119,7 +118,6 @@ files:
|
|
119
118
|
- lib/rmtools/core/regexp.rb
|
120
119
|
- lib/rmtools/core/class.rb
|
121
120
|
- lib/rmtools/core/proc.rb
|
122
|
-
- lib/rmtools/lang/helpers.rb
|
123
121
|
- lib/rmtools/lang/ansi.rb
|
124
122
|
- lib/rmtools/lang/regexp.rb
|
125
123
|
- lib/rmtools/lang/cyrillic.rb
|
@@ -163,6 +161,7 @@ files:
|
|
163
161
|
- lib/rmtools/require.rb
|
164
162
|
- lib/rmtools/xml.rb
|
165
163
|
- lib/rmtools/conversions.rb
|
164
|
+
- lib/rmtools/conversions/json.rb
|
166
165
|
- lib/rmtools/conversions/string.rb
|
167
166
|
- lib/rmtools/conversions/enum.rb
|
168
167
|
- lib/rmtools/conversions/int.rb
|
@@ -174,7 +173,6 @@ files:
|
|
174
173
|
- ./Manifest.txt
|
175
174
|
- ./License.txt
|
176
175
|
- ./README.txt
|
177
|
-
has_rdoc: true
|
178
176
|
homepage: http://github.com/tinbka
|
179
177
|
licenses: []
|
180
178
|
|
@@ -205,9 +203,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
203
|
requirements: []
|
206
204
|
|
207
205
|
rubyforge_project: rmtools
|
208
|
-
rubygems_version: 1.
|
206
|
+
rubygems_version: 1.8.17
|
209
207
|
signing_key:
|
210
208
|
specification_version: 3
|
211
|
-
summary: Yet another Ruby applied
|
209
|
+
summary: Yet another Ruby applied lib
|
212
210
|
test_files: []
|
213
211
|
|
data/lib/rmtools/lang/helpers.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
RMTools::require 'lang/ansi'
|
3
|
-
|
4
|
-
class String
|
5
|
-
ANSI2UTF = Iconv.new("UTF-8", "WINDOWS-1251").method :iconv
|
6
|
-
UTF2ANSI = Iconv.new("WINDOWS-1251", "UTF-8").method :iconv
|
7
|
-
|
8
|
-
# Actually, for short strings and 1251<->65001 it's much faster to use predefined ANSI2UTF and UTF2ANSI procs
|
9
|
-
def utf(from_encoding='WINDOWS-1251')
|
10
|
-
Iconv.new('UTF-8', from_encoding).iconv(self)
|
11
|
-
end
|
12
|
-
|
13
|
-
def utf!(from_encoding='WINDOWS-1251')
|
14
|
-
replace utf from_encoding
|
15
|
-
end
|
16
|
-
|
17
|
-
def ansi(from_encoding='UTF-8')
|
18
|
-
Iconv.new('WINDOWS-1251', from_encoding).iconv(self)
|
19
|
-
end
|
20
|
-
|
21
|
-
def ansi!(from_encoding='UTF-8')
|
22
|
-
replace ansi from_encoding
|
23
|
-
end
|
24
|
-
end
|