ruby_ex 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/ChangeLog +693 -0
  2. data/NEWS +74 -0
  3. data/SPEC.dyn.yml +6 -6
  4. data/SPEC.gemspec +14 -0
  5. data/SPEC.yml +4 -4
  6. data/lib/abstract.rb +2 -4
  7. data/lib/abstract_node.rb +1 -2
  8. data/lib/algorithms/simulated_annealing.rb +50 -29
  9. data/lib/attributed_class.rb +50 -21
  10. data/lib/auto_object.rb +102 -0
  11. data/lib/blank_slate.rb +102 -0
  12. data/lib/cache.rb +1 -2
  13. data/lib/choose.rb +165 -163
  14. data/lib/commands.rb +2 -3
  15. data/lib/commands/command.rb +47 -20
  16. data/lib/commands/datas.rb +1 -1
  17. data/lib/commands/datas/composite.rb +5 -1
  18. data/lib/commands/datas/data.rb +102 -5
  19. data/lib/commands/datas/factory.rb +13 -6
  20. data/lib/commands/datas/temp.rb +3 -5
  21. data/lib/commands/factory.rb +1 -1
  22. data/lib/commands/helpers.rb +1 -1
  23. data/lib/commands/pipe.rb +10 -1
  24. data/lib/commands/runners.rb +1 -1
  25. data/lib/commands/runners/exec.rb +1 -1
  26. data/lib/commands/runners/fork.rb +3 -16
  27. data/lib/commands/runners/mock.rb +67 -0
  28. data/lib/commands/runners/runner.rb +5 -3
  29. data/lib/commands/runners/system.rb +1 -1
  30. data/lib/commands/seq.rb +2 -1
  31. data/lib/config_file.rb +10 -2
  32. data/lib/const_regexp.rb +1 -2
  33. data/lib/{dlogger.rb → d_logger.rb} +1 -2
  34. data/lib/daemon.rb +1 -2
  35. data/lib/diff.rb +1 -2
  36. data/lib/drb/drb_observable.rb +1 -2
  37. data/lib/drb/drb_observable_pool.rb +2 -2
  38. data/lib/drb/drb_service.rb +1 -2
  39. data/lib/drb/drb_undumped_attributes.rb +1 -2
  40. data/lib/drb/drb_undumped_indexed_object.rb +1 -2
  41. data/lib/drb/insecure_protected_methods.rb +1 -2
  42. data/lib/drb_ex.rb +2 -2
  43. data/lib/file_type.rb +466 -0
  44. data/lib/generate_id.rb +12 -6
  45. data/lib/genpasswd.rb +22 -0
  46. data/lib/hash_eval.rb +83 -0
  47. data/lib/histogram.rb +1 -2
  48. data/lib/hookable.rb +3 -4
  49. data/lib/hooker.rb +1 -3
  50. data/lib/html_encode.rb +191 -0
  51. data/lib/indexed_node.rb +0 -1
  52. data/lib/io_marshal.rb +4 -2
  53. data/lib/ioo.rb +3 -2
  54. data/lib/kill_all.rb +46 -0
  55. data/lib/labeled_node.rb +0 -1
  56. data/lib/logger_observer.rb +8 -4
  57. data/lib/md5sum.rb +3 -3
  58. data/lib/meta_factory.rb +99 -0
  59. data/lib/method_call.rb +87 -0
  60. data/lib/mocks.rb +12 -0
  61. data/lib/mocks/assertions.rb +50 -0
  62. data/lib/mocks/method_logger.rb +40 -0
  63. data/lib/mocks/mock.rb +64 -0
  64. data/lib/mocks/object.rb +47 -0
  65. data/lib/mocks/observer.rb +38 -0
  66. data/lib/module/autoload_tree.rb +30 -29
  67. data/lib/module/hierarchy.rb +176 -171
  68. data/lib/module/instance_method_visibility.rb +39 -38
  69. data/lib/node.rb +0 -1
  70. data/lib/object_monitor.rb +1 -2
  71. data/lib/object_monitor_activity.rb +1 -2
  72. data/lib/observable.rb +1 -2
  73. data/lib/observable_pool.rb +1 -2
  74. data/lib/{orderedhash.rb → ordered_hash.rb} +41 -5
  75. data/lib/pp_hierarchy.rb +7 -2
  76. data/lib/r_path.rb +307 -0
  77. data/lib/random_generators.rb +7 -20
  78. data/lib/random_generators/random_generator.rb +2 -4
  79. data/lib/random_generators/ruby.rb +4 -2
  80. data/lib/regex_path.rb +124 -0
  81. data/lib/ruby_ex.rb +28 -98
  82. data/lib/safe_eval.rb +1 -2
  83. data/lib/sendmail.rb +14 -17
  84. data/lib/service_manager.rb +1 -2
  85. data/lib/shuffle.rb +6 -2
  86. data/lib/spring.rb +1 -2
  87. data/lib/spring_set.rb +1 -2
  88. data/lib/{symtbl.rb → sym_tbl.rb} +90 -5
  89. data/lib/sym_tbl_gsub.rb +227 -0
  90. data/lib/{synflow.rb → syn_flow.rb} +1 -2
  91. data/lib/text.rb +218 -0
  92. data/lib/timeout_ex.rb +1 -2
  93. data/lib/trace.rb +9 -8
  94. data/lib/uri/druby.rb +1 -2
  95. data/lib/uri/file.rb +1 -1
  96. data/lib/uri/ftp_ex.rb +1 -1
  97. data/lib/uri/http_ex.rb +1 -1
  98. data/lib/uri/mysql.rb +121 -0
  99. data/lib/uri/pgsql.rb +19 -38
  100. data/lib/uri/svn.rb +1 -2
  101. data/lib/uri_ex.rb +45 -3
  102. data/lib/verbose_object.rb +181 -38
  103. data/lib/yaml/chop_header.rb +19 -11
  104. data/lib/yaml/transform.rb +17 -11
  105. data/lib/yaml/yregexpath.rb +11 -5
  106. data/test/algorithms/simulated_annealing_test.rb +2 -2
  107. data/test/resources/foo.tar.gz +0 -0
  108. data/test/resources/tar.gz.log +49 -0
  109. data/test/sanity-suite.yml +5 -7
  110. data/test/sanity/multiple-requires.yml +17 -7
  111. data/test/sanity/single-requires.yml +38 -20
  112. data/test/stress-tests/threads_and_exceptions.yml +13 -0
  113. data/test/test-unit-setup.rb +3 -1
  114. data/test/unit-suite.yml +7 -8
  115. metadata +42 -31
  116. data/lib/algorithms.rb +0 -12
  117. data/lib/ask.rb +0 -100
  118. data/lib/checkout.rb +0 -12
  119. data/lib/dumpable_proc.rb +0 -57
  120. data/lib/filetype.rb +0 -229
  121. data/lib/thread_mutex.rb +0 -11
  122. data/lib/yaml/basenode_ext.rb +0 -63
data/lib/shuffle.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
2
  # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
3
3
  # License:: GNU General Public License (GPL).
4
- # Revision:: $Id: shuffle.rb 279 2005-06-05 17:46:53Z ertai $
4
+ # Revision:: $Id: shuffle.rb 339 2005-09-06 23:27:27Z ertai $
5
5
 
6
- class Array
6
+ module Shuffle
7
7
 
8
8
  def shuffle! ( generator=nil )
9
9
  n = size
@@ -25,6 +25,10 @@ class Array
25
25
  dup.swap!(i, j)
26
26
  end
27
27
 
28
+ end # module Shuffle
29
+
30
+ class Array
31
+ include Shuffle
28
32
  end # class Array
29
33
 
30
34
 
data/lib/spring.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  # License: Gnu General Public License.
4
4
 
5
5
  # $LastChangedBy: ertai $
6
- # $Id: spring.rb 279 2005-06-05 17:46:53Z ertai $
6
+ # $Id: spring.rb 339 2005-09-06 23:27:27Z ertai $
7
7
 
8
8
 
9
- require 'ruby_ex'
10
9
  require 'thread'
11
10
  require 'observer'
12
11
 
data/lib/spring_set.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  # License: Gnu General Public License.
4
4
 
5
5
  # $LastChangedBy: ertai $
6
- # $Id: spring_set.rb 279 2005-06-05 17:46:53Z ertai $
6
+ # $Id: spring_set.rb 339 2005-09-06 23:27:27Z ertai $
7
7
 
8
8
 
9
- require 'spring'
10
9
 
11
10
 
12
11
  class SpringSet
@@ -3,9 +3,8 @@
3
3
  # License: Ruby license.
4
4
 
5
5
  # $LastChangedBy: ertai $
6
- # $Id: symtbl.rb 279 2005-06-05 17:46:53Z ertai $
6
+ # $Id: sym_tbl.rb 339 2005-09-06 23:27:27Z ertai $
7
7
 
8
- require 'ruby_ex'
9
8
  require 'set'
10
9
 
11
10
  class SymTbl
@@ -15,12 +14,23 @@ class SymTbl
15
14
  attr_reader :sid, :local, :father
16
15
 
17
16
  def initialize ( father_env=nil, default=nil )
18
- @father = father_env
19
17
  @sid = (@@sid += 1)
20
18
  @local = Hash.new(default)
19
+ if father_env.is_a? Hash
20
+ @father = nil
21
+ merge!(father_env)
22
+ else
23
+ @father = father_env
24
+ end
25
+ end
26
+
27
+ def key_convert ( aKey )
28
+ (aKey.is_a? Symbol)? aKey : aKey.to_s.to_sym
21
29
  end
22
30
 
23
31
  def [] ( aKey )
32
+ return nil if aKey == ''
33
+ aKey = key_convert(aKey)
24
34
  if @local.has_key? aKey
25
35
  @local[aKey]
26
36
  elsif @father.nil?
@@ -31,6 +41,7 @@ class SymTbl
31
41
  end
32
42
 
33
43
  def []= ( aKey, aValue )
44
+ aKey = key_convert(aKey)
34
45
  @local[aKey] = aValue
35
46
  end
36
47
 
@@ -62,15 +73,60 @@ class SymTbl
62
73
  ancestors.map{ |s| s.desc_one }.to_yaml
63
74
  end
64
75
 
76
+ def merge(other)
77
+ symtbl = self.class.new(self)
78
+ symtbl.merge!(other)
79
+ end
80
+
81
+ def merge!(other)
82
+ other.each { |k, v| @local[key_convert(k)] = v }
83
+ self
84
+ end
85
+
86
+ alias update merge!
87
+
88
+ def has_key?(key)
89
+ key = key_convert(key)
90
+ if @local.has_key?(key)
91
+ true
92
+ else
93
+ if @father.nil?
94
+ false
95
+ else
96
+ @father.has_key?(key)
97
+ end
98
+ end
99
+ end
100
+
101
+ alias key? has_key?
102
+ alias include? has_key?
103
+ alias member? has_key?
104
+
105
+ def has_local_key?(key)
106
+ @local.has_key?(key_convert(key))
107
+ end
108
+
109
+ def new_child
110
+ self.class.new(self)
111
+ end
112
+
65
113
  end # class SymTbl
66
114
 
67
115
 
68
116
 
69
117
  test_section __FILE__ do
70
118
 
71
- require 'ruby_ex'
72
119
  class SymTblTest < Test::Unit::TestCase
73
120
 
121
+ def setup
122
+ @father = SymTbl.new
123
+ @father[:a] = 0
124
+ @father[:b] = 1
125
+ @son = SymTbl.new(@father)
126
+ @son[:a] = 10
127
+ @son[:c] = 2
128
+ end
129
+
74
130
  def test1
75
131
  root = SymTbl.new
76
132
 
@@ -99,10 +155,39 @@ test_section __FILE__ do
99
155
 
100
156
  assert_equal(42, sub2[:a], 't8')
101
157
 
102
- assert_equal([{2=>{:a=>42}}, {1=>{:a=>2, :c=>3}}, {0=>{:b=>1, :a=>0}}],
158
+ assert_equal([{4=>{:a=>42}}, {3=>{:a=>2, :c=>3}}, {2=>{:b=>1, :a=>0}}],
103
159
  YAML::load(sub2.desc))
104
160
  end
105
161
 
162
+ def test_has_key?
163
+ assert(@son.has_key?(:a))
164
+ assert(@son.has_key?(:b))
165
+ assert(@son.has_key?(:c))
166
+ assert(! @son.has_key?(:not_a_key))
167
+ end
168
+
169
+ def test_merge!
170
+ s = SymTbl.new
171
+ s[:a] = 40
172
+ s[:c] = 42
173
+ @son.merge!(s)
174
+ assert_equal(40, @son[:a])
175
+ assert_equal(42, @son[:c])
176
+ end
177
+
178
+ def test_merge
179
+ s = SymTbl.new
180
+ s[:a] = 40
181
+ s[:c] = 42
182
+ r = @son.merge(s)
183
+ assert_equal(10, @son[:a])
184
+ assert_equal(2, @son[:c])
185
+ assert_equal(40, r[:a])
186
+ assert_equal(1, r[:b])
187
+ assert_equal(42, r[:c])
188
+ assert_equal(@son, r.father)
189
+ end
190
+
106
191
  end # class SymTblTest
107
192
 
108
193
  end
@@ -0,0 +1,227 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
3
+ # License:: Ruby License
4
+ # Revision:: $Id: sym_tbl_gsub.rb 339 2005-09-06 23:27:27Z ertai $
5
+
6
+ require 'sym_tbl'
7
+
8
+ class Object
9
+
10
+ def symtbl_gsub ( symtbl )
11
+ nil
12
+ end
13
+
14
+ def do_symtbl_gsub ( symtbl )
15
+ result = symtbl_gsub(symtbl)
16
+ return (result.nil?)? self : result
17
+ end
18
+
19
+ def symtbl_to_s
20
+ to_s
21
+ end
22
+
23
+ end # class Object
24
+
25
+
26
+
27
+ module PrettyInspect
28
+ def symtbl_to_s
29
+ inspect
30
+ end
31
+ end # module PrettyInspect
32
+
33
+
34
+
35
+ class Hash
36
+ have PrettyInspect
37
+
38
+ def symtbl_gsub ( symtbl )
39
+ changed = false
40
+ res = self.class.new
41
+ each do |k,v|
42
+ new_k = k.symtbl_gsub(symtbl)
43
+ new_v = v.symtbl_gsub(symtbl)
44
+ changed = true if new_k or new_v
45
+ res[new_k || k] = (new_v || v)
46
+ end
47
+ changed ? res : nil
48
+ end
49
+
50
+ end # class Hash
51
+
52
+
53
+
54
+ class Array
55
+ have PrettyInspect
56
+
57
+ def symtbl_gsub ( symtbl )
58
+ changed = false
59
+ res = self.class.new
60
+ each do |e|
61
+ changed = true if new_e = e.symtbl_gsub(symtbl)
62
+ res << (new_e || e)
63
+ end
64
+ changed ? res : nil
65
+ end
66
+
67
+ end # class Array
68
+
69
+
70
+
71
+ class SymTbl
72
+
73
+ def symtbl_gsub! ( symtbl )
74
+ new_local = @local.symtbl_gsub(symtbl)
75
+ return nil if new_local.nil?
76
+ @local = new_local
77
+ self
78
+ end
79
+
80
+ def symtbl_gsub ( symtbl )
81
+ dup.symtbl_gsub!(symtbl)
82
+ end
83
+
84
+ end # class SymTbl
85
+
86
+
87
+
88
+ class Pathname
89
+
90
+ def symtbl_gsub ( symtbl )
91
+ res = to_s.symtbl_gsub(symtbl)
92
+ return self.class.new(res) unless res.nil?
93
+ end
94
+
95
+ end # class Pathname
96
+
97
+
98
+
99
+ class Regexp
100
+ have PrettyInspect
101
+
102
+ def symtbl_gsub ( symtbl )
103
+ res = source.symtbl_gsub(symtbl)
104
+ return self.class.new(res) unless res.nil?
105
+ end
106
+
107
+ end # class Regexp
108
+
109
+
110
+
111
+ class Symbol
112
+
113
+ def symtbl_gsub ( symtbl )
114
+ res = to_s.symtbl_gsub(symtbl)
115
+ return res.to_sym unless res.nil?
116
+ end
117
+
118
+ end # class Symbol
119
+
120
+
121
+
122
+ class String
123
+
124
+ def symtbl_gsub ( symtbl )
125
+ return nil unless self =~ /<<(.*)>>/
126
+ cur, last = self, nil
127
+ while cur != last
128
+ last = cur
129
+ cur = cur.gsub(/<<([^<>]*)>>/) do
130
+ s = symtbl[$1]
131
+ (s.nil?)? $& : s.symtbl_to_s
132
+ end
133
+ end
134
+ (cur == self)? nil : cur
135
+ end
136
+
137
+ end # class String
138
+
139
+
140
+ PathList.import!
141
+ class PathList
142
+
143
+ alias add_matching_without_expand add_matching
144
+ def add_matching(pattern)
145
+ pattern = @expand[pattern] if defined? @expand and @expand
146
+ add_matching_without_expand pattern
147
+ end
148
+ protected :add_matching
149
+
150
+ def symtbl_gsub! ( symtbl )
151
+ @expand = lambda { |pattern| pattern.do_symtbl_gsub(symtbl) }
152
+ map! { |path| path.do_symtbl_gsub(symtbl) }
153
+ @expand = nil
154
+ self
155
+ end
156
+
157
+ def symtbl_gsub ( symtbl )
158
+ dup.symtbl_gsub!(symtbl)
159
+ end
160
+
161
+ end # class PathList
162
+
163
+
164
+
165
+ module SymTblGsub
166
+
167
+ test_section __FILE__ do
168
+ class SymTblGsubTest < Test::Unit::TestCase
169
+ def setup
170
+ @s = SymTbl.new(
171
+ :foo => :bar,
172
+ :bar => [1, 2],
173
+ 3 => 'foo',
174
+ :i => '<<j>>',
175
+ :j => '<<3>>',
176
+ :pwd => __FILE__.to_path.dirname.to_s
177
+ )
178
+ end
179
+ def assert_symtbl ( my, ref=nil )
180
+ assert_equal ref, my.symtbl_gsub(@s)
181
+ end
182
+ def test_string
183
+ assert_symtbl '<<foo>>', 'bar'
184
+ assert_symtbl '<<foo>><<3>> >> <<', 'barfoo >> <<'
185
+ assert_symtbl '<<<<>>>>%%><<>>^#^#'
186
+ assert_symtbl '<<<<bar>>>>', '<<[1, 2]>>'
187
+ assert_symtbl '%<<<<foo>>>>#', '%[1, 2]#'
188
+ assert_symtbl "_\n\t\000_<<i>>__", "_\n\t\000_foo__"
189
+ assert_symtbl '<<<<i>>>>', 'bar'
190
+ assert_symtbl '<<dne>> <<foo>>', '<<dne>> bar'
191
+ end
192
+ class Foo
193
+ end
194
+ def test_object
195
+ assert_symtbl Foo.new
196
+ end
197
+ def test_hash
198
+ assert_symtbl({'<<foo>>' => '<<i>>', 'barbar' => '<<3>>' },
199
+ {'barbar'=>'foo', 'bar'=>'foo'})
200
+ end
201
+ def test_array
202
+ assert_symtbl(['<<foo>>', '<<i>>', 'barbar <<3>>' ],
203
+ ['bar', 'foo', 'barbar foo'])
204
+ end
205
+ def test_pathname
206
+ assert_symtbl('foo/<<foo>>/<<i>>'.to_path, 'foo/bar/foo'.to_path)
207
+ end
208
+ def test_regexp
209
+ assert_symtbl(/<<foo>>(<<i>>)*/, /bar(foo)*/)
210
+ end
211
+ def test_symbol
212
+ assert_symtbl(:'<<foo>> <<i>>', :'bar foo')
213
+ end
214
+ def test_pathlist
215
+ pathlist = ['<<foo>>', '<<i>>'.to_path]
216
+ ls1 = '<<bing>>/../test'.to_path + 'resources/autoload_tree/*.rb'
217
+ ls2 = '<<pwd>>/../test'.to_path + 'resources/autoload_tree/*.rb'
218
+ pathlist << ls2 << ls1
219
+ my = PathList[pathlist].symtbl_gsub(@s).map! { |x| x.basename }
220
+ my.all? { |x| assert_kind_of(Pathname, x) }
221
+ ref = %w[ bar foo A.rb B.rb ]
222
+ assert_equal ref.to_set, my.map!{ |x| x.to_s }.to_set
223
+ end
224
+ end # class SymTblGsubTest
225
+ end
226
+
227
+ end # module SymTblGsub
@@ -10,7 +10,6 @@
10
10
  # parallel systems.
11
11
  #
12
12
 
13
- require 'ruby_ex'
14
13
  require 'thread'
15
14
  require 'set'
16
15
 
@@ -146,7 +145,7 @@ class SynFlowFactory
146
145
  @transitions.include?(*transition)
147
146
  end
148
147
 
149
-
148
+
150
149
  def delta ( src, label )
151
150
  @transitions.delta(src, label)
152
151
  end
data/lib/text.rb ADDED
@@ -0,0 +1,218 @@
1
+ # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
2
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
3
+ # License:: Gnu General Public License.
4
+ # Revision:: $Id: text.rb 359 2005-09-16 10:05:22Z ertai $
5
+
6
+ class Text
7
+
8
+ attr_accessor :text, :width, :cut_if_needed
9
+
10
+ @@default_options = { :width => 78, :cut_if_needed => false }.freeze
11
+
12
+ # options:
13
+ # width: the maximal line width (default 78)
14
+ # cut_if_needed: see cropping
15
+ def initialize ( text, options={} )
16
+ options = @@default_options.merge options
17
+ @text = text
18
+ @width = options[:width]
19
+ @cut_if_needed = options[:cut_if_needed]
20
+ end
21
+
22
+
23
+
24
+ def justify! ( &block )
25
+ input = @text.to_a
26
+ @text, block = '', method(:adder) if block.nil?
27
+ last_line = input.size - 1
28
+ input.each_with_index do |line, i|
29
+ line =~ /^(\s*)(.*)\s*?(\n?)$/
30
+ indent, base, eol = $1, $2, $3
31
+ words = base.split(/\s+/)
32
+ base = words.join(' ')
33
+ width = indent.width + base.width
34
+ unless width > @width or base.empty? or i == last_line
35
+ spaces = words.size - 1
36
+ padding_size = @width - width
37
+ if spaces > 0
38
+ nb = ' ' * (padding_size / spaces + 1)
39
+ nb2 = nb + ' '
40
+ rest = padding_size % spaces + 1
41
+ base.gsub!(/ /) do
42
+ rest -= 1
43
+ (rest >= 0) ? nb2 : nb
44
+ end
45
+ end
46
+ end
47
+ block[indent, base, eol]
48
+ end
49
+ self
50
+ end
51
+
52
+
53
+
54
+ def split! ( &block )
55
+ last_new_line = (@text[-1] == ?\n)? "\n" : ''
56
+ indent = @text[/\A([ \t]*)/, 1]
57
+ words = @text.split(/\s+/)
58
+ @text, block = '', method(:adder) if block.nil?
59
+
60
+ line = ''
61
+ while not words.empty?
62
+ words.shift if words.first.empty?
63
+ word = words.first
64
+ if indent.width + line.width + word.width + 1 <= @width
65
+ line += ' ' unless line.empty?
66
+ line += word
67
+ words.shift
68
+ elsif line.empty?
69
+ if @cut_if_needed
70
+ line = word[0..width-1]
71
+ words[0] = word[width..-1]
72
+ block[indent, line, "\n"]
73
+ line = ''
74
+ else
75
+ block[indent, word, "\n"]
76
+ words.shift
77
+ end
78
+ else
79
+ block[indent, line, "\n"]
80
+ line = ''
81
+ end
82
+ end
83
+
84
+ block[indent, line, last_new_line] unless line.empty?
85
+ self
86
+ end
87
+
88
+
89
+
90
+ def split_and_justify! ( &block )
91
+ split!.justify!(&block)
92
+ end
93
+
94
+
95
+ def crop! ( width=@width, message=" ...\n", &block )
96
+ input = @text
97
+ @text, block = '', method(:adder) if block.nil?
98
+ message = message.to_s
99
+ width2 = width - 1 - message.chomp.width
100
+ raise ArgumentError, "Bad width: too low" if width2 < 0
101
+ input.each do |line|
102
+ if line.width > width
103
+ block[line[0..width2], message]
104
+ else
105
+ block[line]
106
+ end
107
+ end
108
+ self
109
+ end
110
+
111
+
112
+ def clip! ( head_size=100, tail_size=30, message="\n[...clipped...]\n\n", &block )
113
+ input = @text.to_a
114
+ size = input.size
115
+ return identity!(&block) if head_size + tail_size >= size
116
+ head = (head_size - 1 < 0)? [] : input[0 .. head_size - 1]
117
+ tail = input[[0, size - tail_size, head_size].max .. -1]
118
+ @text, block = '', method(:adder) if block.nil?
119
+ head.each(&block)
120
+ message.each(&block)
121
+ tail.each(&block)
122
+ self
123
+ end
124
+
125
+
126
+ def adder ( *args )
127
+ @text += args.join
128
+ end
129
+
130
+
131
+ def identity! ( &block )
132
+ @text.each(&block) unless block.nil?
133
+ self
134
+ end
135
+
136
+
137
+ def clear
138
+ @text.clear
139
+ end
140
+
141
+
142
+ def mask!
143
+ @text = '*****'.to_text
144
+ end
145
+
146
+
147
+ def to_s
148
+ @text.dup
149
+ end
150
+
151
+
152
+ # Redirect calls like `justify' to `dup.justify!'
153
+ def method_missing ( meth, *args, &block )
154
+ in_place_meth = :"#{meth}!"
155
+ return super unless respond_to? in_place_meth
156
+ dup.send(in_place_meth, *args, &block)
157
+ end
158
+
159
+ end # class Text
160
+
161
+
162
+ class String
163
+ def to_text ( *args, &block )
164
+ Text.new(self, *args, &block)
165
+ end
166
+ end # class String
167
+
168
+
169
+ test_section __FILE__ do
170
+
171
+ class TestText < ::Test::Unit::TestCase
172
+
173
+ def setup
174
+ @o = { :width => 10 }
175
+ @text = " foofoof barbarfoo foo f bar for na goo baz buz g"
176
+ @cropped = " foofo ...\n"
177
+ @splitted = " foofoof\n barbarfoo\n foo f bar\n for na\n goo baz\n buz g"
178
+ @splitted_justified = " foofoof\n barbarfoo\n foo f bar\n for na\n goo baz\n buz g"
179
+ @splitted_justified_cropped = " foofoof\n barba ...\n foo ...\n for ...\n goo ...\n buz g"
180
+ @clipped = " foofoof\n barbarfoo\n\n[...clipped...]\n\n buz g"
181
+ end
182
+
183
+ def teardown
184
+ end
185
+
186
+ def test_justify
187
+ assert_equal @splitted_justified, @splitted.to_text(@o).justify.text
188
+ end
189
+
190
+ def test_split
191
+ assert_equal @splitted, @text.to_text(@o).split.text
192
+ end
193
+
194
+ def test_split_and_justify
195
+ assert_equal @splitted_justified, @text.to_text(@o).split_and_justify.text
196
+ end
197
+
198
+ def test_crop
199
+ assert_equal @cropped, @text.to_text(@o).crop.text
200
+ assert_equal @splitted_justified_cropped, @splitted_justified.to_text(@o).crop.text
201
+ end
202
+
203
+ def test_clip
204
+ assert_equal @clipped, @splitted_justified.to_text(@o).clip(2, 1).text
205
+ assert_equal 'yo', @splitted_justified.to_text(@o).clip(0, 0, 'yo').text
206
+ assert_equal " foofoof\nyo", @splitted_justified.to_text(@o).clip(1, 0, 'yo').text
207
+ assert_equal 'yo buz g', @splitted_justified.to_text(@o).clip(0, 1, 'yo').text
208
+ assert_equal @splitted_justified, @splitted_justified.to_text(@o).clip(100, 0, 'yo').text
209
+ assert_equal @splitted_justified, @splitted_justified.to_text(@o).clip(6, 0, 'yo').text
210
+ assert_equal @splitted_justified, @splitted_justified.to_text(@o).clip(0, 6, 'yo').text
211
+ assert_equal @splitted_justified, @splitted_justified.to_text(@o).clip(3, 3, 'yo').text
212
+ assert_equal " foofoof\n barbarfoo\nyo for na\n goo baz\n buz g",
213
+ @splitted_justified.to_text(@o).clip(2, 3, 'yo').text
214
+ end
215
+
216
+ end # class TestText
217
+
218
+ end