ruby_ex 0.1.2 → 0.2.0

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.
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