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 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.3'
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 framework'
12
- self.description = 'Applied framework primarily for debug and text/arrays/files operation.'
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].count
242
+ * [1, 2, 2, 2, 3, 3].arrange
243
243
  * => {1=>1, 2=>3, 3=>2}
244
- * [1, 2, 2, 2, 3, 3].count {|i| i%2}
244
+ * [1, 2, 2, 2, 3, 3].arrange {|i| i%2}
245
245
  * => {0=>3, 1=>3}
246
- * [1, 2, 2, 2, 3, 3].count :fill
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].count :indexes
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].count(:indexes) {|i| i%2}
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].count(:group) {|i| i%2}
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, "count", RUBY_METHOD_FUNC(rb_ary_count_items), -1);
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
@@ -14,6 +14,9 @@ end
14
14
  class Proc
15
15
  def b; (self != NULL) && self end
16
16
  end
17
+ class NilClass
18
+ def b; false end
19
+ end
17
20
  module Enumerable
18
21
  def b; !empty? && self end
19
22
  end
@@ -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
- effect = Effects[num] if !num
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- require 'cgi'
2
+ #require 'cgi'
3
3
 
4
4
  module Enumerable
5
5
 
@@ -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
@@ -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
@@ -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
- [Hash, Regexp, File, Dir, Range, Class, Module].each {|klass| klass.__init__}
49
+ require 'set'
50
+ [Hash, Array, Set, Regexp, File, Dir, Range, Class, Module].each {|klass| klass.__init__}
@@ -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
 
@@ -22,7 +22,7 @@ class Module
22
22
  end
23
23
 
24
24
  def self_name
25
- @self_name ||= name.match[/[^:]+$/]
25
+ @self_name ||= name.match(/[^:]+$/)
26
26
  end
27
27
 
28
28
  def my_methods filter=//
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
  class Proc
3
3
  NULL = lambda {} unless defined? Proc::NULL
4
+ TRUE = lambda {true} unless defined? Proc::TRUE
5
+ FALSE = lambda {false} unless defined? Proc::FALSE
4
6
  attr_accessor :string
5
7
 
6
8
  def when
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
- require 'openssl/ssl'
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
- BlackHole.new
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 << args}
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<<pattern
257
+ $log <= pattern
258
258
  add_instruction(pattern) {|s, m|
259
259
  $log << m
260
260
  yield s, arguments(s, m)
@@ -44,20 +44,34 @@ module RMTools
44
44
  end
45
45
 
46
46
  def defaults
47
- puts %{ :q => false, # not print
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
- :caller => "#{@c.gray('%f:%l')} #{@c.red_bold(':%m')}", # file:line :method
52
- :format => "%time %mode [%caller]: %text" # format of entire log string, %mode is {#{%w(debug log info warn).map {|i| @highlight[i.to_sym]}*', '}}}
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
- :time => ["%H:%M:%S", "%03d"],
59
- :caller => "#{@c.gray('%f:%l')} #{@c.red_bold(':%m')}",
60
- :format => "%time %mode [%caller]: %text"
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.sub! "%mode", @highlight[mode]
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.sub! "%time", time
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.sub! "%caller", caler.sub(String::CALLER_RE, cfg.cf)
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_
@@ -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 = (Time.now.to_f*1000).round
13
- t1 = (t1.to_f*1000).round
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...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"}"
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) count(:group, &b) end
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{^(#{(%w{every no select reject partition find_all find sum foldr}+instance_methods.grep(/_by$/))*'|'})_([\w\d\_]+[!?]?)}
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
- iterator = :every? if iterator == :every
24
- iterator = :no? if iterator == :no
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.find_include?(number_or_range)
209
+ @ranges.find {|r| r.include?(number_or_range)}
200
210
  end
201
211
 
202
212
  def begin
@@ -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
- def self.include?(name, str)
11
- f = new name, 'r'
12
- incl = f.include? str
13
- f.close
14
- incl
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]}.count.to_a
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[0]})"
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[0]})"
73
+ warn "couldn't read from #{dest.inspect}; file missed (called from #{caller[2]})"
74
74
  end
75
75
  end
76
76
  }
@@ -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='rmtools', version='\d')
7
- gem = Gem.source_index.select {|a| a[0] =~ /^#{ext_name}-#{version}$/}[0]
8
- return unless gem
9
- gemspec = gem[1]
10
- path = gemspec.full_gem_path
11
- !gemspec.files.grep(/^ext\//).find {|f|
12
- !(File.file?(installed=File.join(path, f)) and IO.read(f) == IO.read(installed))
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
- fs = Dir.new('.').recursive_content
18
- RMTools.rw 'Manifest.txt', (exc ? fs.reject {|i| i[/^(#{exc*'|'})\//]} : fs)*"\n"
15
+ fs = Dir.new('.').recursive_content
16
+ RMTools.rw 'Manifest.txt', (exc ? fs.reject {|i| i[/^(#{exc*'|'})\//]} : fs)*"\n"
19
17
  end
@@ -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 >= '1.9'
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/helpers'
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
- def csqueeze
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 just
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 cjust(*args)
84
- ANSI2UTF[UTF2ANSI[self].just(*args)]
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
 
@@ -3,7 +3,10 @@ RMTools::require 'lang/cyrillic'
3
3
 
4
4
  class Regexp
5
5
 
6
- def cyr_ic() Regexp.new(source.cyr_ic, options) end
7
- alias :ci :cyr_ic
6
+ if RUBY_VERSION > '1.9'
7
+ def ci; self end
8
+ else
9
+ def ci; Regexp.new(source.cyr_ic, options) end
10
+ end
8
11
 
9
12
  end
@@ -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) == '\\'
@@ -30,7 +30,7 @@ class String
30
30
  'pathname' => m[5] || '/',
31
31
  'path' => m[6] || '',
32
32
  'ext' => m[7],
33
- 'query' => m[8] && m[8].to_hash(false),
33
+ 'query' => m[8] && m[8].to_params(false),
34
34
  'anchor' => m[9] }
35
35
  when :caller
36
36
  m = match CALLER_RE
@@ -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
- [/[^.?!]+\z/, /[^;]+\z/, /[^\n]+/, /\S+\z/, /[^。]+z/, /[^、]+z/].each {|t|
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] ||= RUBY_VERSION < '1.9' && cyr? ? 2 : 1
122
+ opts[:charsize] ||= cyr? ? 2 : 1
122
123
  return self if size <= maxlen
123
- maxlen -= 3
124
- split_to_blocks(maxlen*opts[:charsize], terminator, :strips => true, :strict_overhead => false, :lines => 1)[0][0, maxlen].chomp('.') + '...'
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 [:flags], :strips=>true
140
- a = split("\n")
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- RMTools::require 'lang/helpers'
2
+ RMTools::require 'lang/ansi'
3
3
 
4
4
  class String
5
5
 
@@ -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: 25
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 3
10
- version: 1.2.3
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-02-02 00:00:00 +03:00
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 framework primarily for debug and text/arrays/files operation.
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.5.0
206
+ rubygems_version: 1.8.17
209
207
  signing_key:
210
208
  specification_version: 3
211
- summary: Yet another Ruby applied framework
209
+ summary: Yet another Ruby applied lib
212
210
  test_files: []
213
211
 
@@ -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