rmtools 1.2.3 → 1.2.7
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/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
|