plain_text 0.7.1 → 0.8

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.
@@ -47,8 +47,8 @@ module PlainText
47
47
  # @param size_even [Boolean] if true (Def: false), the sizes of the returned arrays are guaranteed to be identical.
48
48
  # @param filler [Object] if size_even: is true and if matching is performed, this filler is added at the end of the last element.
49
49
  def even_odd_arrays(ary, size_even: false, filler: "")
50
- ar_even = select.with_index { |_, i| i.even? } rescue select.each_with_index { |_, i| i.even? } # Rescue for Ruby 2.1 or earlier
51
- ar_odd = select.with_index { |_, i| i.odd? } rescue select.each_with_index { |_, i| i.odd? } # Rescue for Ruby 2.1 or earlier
50
+ ar_even = ary.select.with_index { |_, i| i.even? } rescue ary.select.each_with_index { |_, i| i.even? } # Rescue for Ruby 2.1 or earlier
51
+ ar_odd = ary.select.with_index { |_, i| i.odd? } rescue ary.select.each_with_index { |_, i| i.odd? } # Rescue for Ruby 2.1 or earlier
52
52
  if size_even && (ar_even.size != ar_odd.size)
53
53
  ar_odd.push filler
54
54
  raise "Should not happern." if (ar_even.size != ar_odd.size)
@@ -61,14 +61,15 @@ module PlainText
61
61
  # If positive or zero, it returns i.
62
62
  # If the negative index is out of range, it returns nil.
63
63
  #
64
+ # @see #positive_array_index_checked
64
65
  # @param i [Integer]
65
- # @param ary [Array, Integer, nil] Reference Array or its size (Array#size) or nil (interpreted as self#size (untested)).
66
+ # @param arysize [Array, Integer] Reference Array or its size (Array#size).
66
67
  # @return [Integer, NilClass] nil if out of range to the negative. Note in most cases in Ruby default, it raises IndexError. See the code of {#positive_array_index_checked}
67
68
  # @raise [TypeError] if non-integer is specified.
68
- # @raise [ArgumentError] if ary is neither an Array nor Integer, or more specifically, it does not have size method or ary.size does not return Integer or similar.
69
- def positive_array_index(i, ary=nil)
70
- arysize = (ary ? (ary.respond_to?(:to_int) ? ary.to_int : ary.size) : size)
71
- i2 = i.to_int rescue (raise TypeError, sprintf("no implicit conversion of #{i.class} into Integer (i=#{i.inspect},ary=#{ary.inspect})"))
69
+ # @raise [ArgumentError] if arysize is neither an Array nor Integer, or more specifically, it does not have size method or arysize.size does not return Integer or similar.
70
+ def positive_array_index(i, arysize=nil)
71
+ arysize = (arysize.respond_to?(:to_int) ? arysize.to_int : arysize.size)
72
+ i2 = i.to_int rescue (raise TypeError, sprintf("no implicit conversion of #{i.class} into Integer (i=#{i.inspect},arysize=#{arysize.inspect})"))
72
73
  return i2 if i2 >= 0
73
74
  ret = arysize + i2 rescue (raise ArgumentError, "Reference is neither an Array nor Integer.")
74
75
  (ret < 0) ? nil : ret
@@ -82,20 +83,20 @@ module PlainText
82
83
  # Wrapper for {#positive_array_index}
83
84
  #
84
85
  # @param index_in [Integer] Index to check and convert from. Potentially negative integer.
85
- # @param ary [Array, Integer, nil] Reference Array or its size (Array#size) or nil (interpreted as self#size (untested)).
86
+ # @param arysize [Array, Integer] Reference Array or its size (Array#size).
86
87
  # @param accept_too_big [Boolean, NilClass] if true (Default), a positive index larger than the last array index is returned as it is. If nil, the last index + 1 is accepted but raises an Exception for anything larger. If false, any index larger than the last index raises an Exception.
87
88
  # @param varname [NilClass, String] Name of the variable (or nil) to be used for error messages.
88
89
  # @return [Integer] Non-negative index; i.e., if index=-1 is specified for an Array with a size of 3, the returned value is 2 (the last index of it).
89
90
  # @raise [IndexError] if the index is out of the range to negative.
90
- # @raise [ArgumentError] if ary is neither an Array nor Integer, or more specifically, it does not have size method or ary.size does not return Integer or similar.
91
- def positive_array_index_checked(index_in, ary=nil, accept_too_big: true, varname: nil)
92
- # def self.positive_valid_index_for_array(index_in, ary, varname: nil)
91
+ # @raise [ArgumentError] if arysize is neither an Array nor Integer, or more specifically, it does not have size method or arysize.size does not return Integer or similar.
92
+ def positive_array_index_checked(index_in, arysize, accept_too_big: true, varname: nil)
93
+ # def self.positive_valid_index_for_array(index_in, arysize, varname: nil)
93
94
  errmsgs = {}
94
95
  %w(of for).each do |i|
95
96
  errmsgs[i] = (varname ? "." : sprintf(" %s %s.", i, varname))
96
97
  end
97
98
 
98
- arysize = (ary ? (ary.respond_to?(:to_int) ? ary.to_int : ary.size) : size)
99
+ arysize = (arysize.respond_to?(:to_int) ? arysize.to_int : arysize.size)
99
100
  index = positive_array_index(index_in, arysize) # guaranteed to be Integer or nil (or ArgumentError)
100
101
  raise IndexError, sprintf("index (%s) too small for array; minimum: -%d", index_in, arysize) if !index # Ruby default Error message (except the variable "index" as opposed to "index_in is used in the true Ruby default).
101
102
  if index_in >= 0
data/lib/plain_text.rb CHANGED
@@ -8,12 +8,17 @@
8
8
  # Many of the methods work on tha basis of a line. For example, {#head} and {#tail} methods
9
9
  # work like the respective UNIX-shell commands, returning a specified line at the head/tail parts of self.
10
10
  #
11
- # Most methods in this module are meant to be included in String, except for a few module functions.
12
- # It is however debatable whether it is a good practice to include a third-party module in the core class.
13
- # This module contains a helper module function {PlainText.extend_this}, with which an object extends this module easily as Singleton if this module is not already included.
11
+ # Many of the methods contained directly in this module are meant to be
12
+ # included in String. Obviously, though, it is debatable if it is
13
+ # a good practice to include a third-party module in the core class.
14
+ #
15
+ # Several module functions are also available.
16
+ # This module contains a helper module function {PlainText.extend_this}, with which
17
+ # an object extends this module easily as Singleton if this module is not already included.
14
18
  #
15
19
  # A few methods in this module assume that {PlainText::Split} is included in String,
16
20
  # which in default is the case, as soon as this file is read (by Ruby's require).
21
+ # The specification may be subject to change in the future release.
17
22
  #
18
23
  # @author Masa Sakano (Wise Babel Ltd)
19
24
  #
@@ -185,7 +190,7 @@ module PlainText
185
190
  # Also, deepcopy is needed, as this method is destructive.
186
191
  prt = (preserve_paragraph ? prt : Part.new([prt.join])).deepcopy
187
192
  end
188
- prt.squash_boundaryies! # Boundaries are squashed.
193
+ prt.squash_boundaries! # Boundaries are squashed.
189
194
 
190
195
  # Handles Boundary
191
196
  clean_text_boundary!(prt, boundary_style: boundary_style)
@@ -407,7 +412,7 @@ module PlainText
407
412
  end # self.clean_text_line_head_tail!
408
413
  private_class_method :clean_text_line_head_tail!
409
414
 
410
- # @param prt [PlainText:Part] (see PlainText.clean_text#prt)
415
+ # @param prt [PlainText::Part] (see PlainText.clean_text#prt)
411
416
  # @param firstlbs_style [Symbol, String] (see PlainText.clean_text#firstlbs_style)
412
417
  # @param lastsps_style [Symbol, String] (see PlainText.clean_text#lastsps_style)
413
418
  # @return [void]
@@ -419,7 +424,6 @@ module PlainText
419
424
  lastsps_style: ,
420
425
  is_debug: false
421
426
  )
422
-
423
427
  # Handles the beginning of the given Part.
424
428
  obj = prt.first_significant_element || return
425
429
  # The first significant element is either Paragraph or Background.
@@ -1050,8 +1054,8 @@ module PlainText
1050
1054
 
1051
1055
  end # module PlainText
1052
1056
 
1053
- require "plain_text/part"
1054
- require "plain_text/parse_rule"
1055
- require "plain_text/split"
1056
- require "plain_text/util"
1057
+ require_relative "plain_text/part"
1058
+ require_relative "plain_text/parse_rule"
1059
+ require_relative "plain_text/split"
1060
+ require_relative "plain_text/util"
1057
1061
 
data/plain_text.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'date'
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{plain_text}.sub(/.*/){|c| (c == File.basename(Dir.pwd)) ? c : raise("ERROR: s.name=(#{c}) in gemspec seems wrong!")}
8
- s.version = "0.7.1".sub(/.*/){|c| fs = Dir.glob('changelog{,.*}', File::FNM_CASEFOLD); raise('More than one ChangeLog exist!') if fs.size > 1; warn("WARNING: Version(s.version=#{c}) already exists in #{fs[0]} - ok?") if fs.size == 1 && !IO.readlines(fs[0]).grep(/^\(Version: #{Regexp.quote c}\)$/).empty? ; c } # n.b., In macOS, changelog and ChangeLog are identical in default.
8
+ s.version = "0.8".sub(/.*/){|c| fs = Dir.glob('changelog{,.*}', File::FNM_CASEFOLD); raise('More than one ChangeLog exist!') if fs.size > 1; warn("WARNING: Version(s.version=#{c}) already exists in #{fs[0]} - ok?") if fs.size == 1 && !IO.readlines(fs[0]).grep(/^\(Version: #{Regexp.quote c}\)$/).empty? ; c } # n.b., In macOS, changelog and ChangeLog are identical in default.
9
9
  # s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
10
  s.bindir = 'bin'
11
11
  %w(countchar textclean head.rb tail.rb yard2md_afterclean).each do |f|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  File.executable?(path) ? s.executables << f : raise("ERROR: Executable (#{path}) is not executable!")
14
14
  end
15
15
  s.authors = ["Masa Sakano"]
16
- s.date = %q{2022-09-09}.sub(/.*/){|c| (Date.parse(c) == Date.today) ? c : raise("ERROR: s.date=(#{c}) is not today!")}
16
+ s.date = %q{2022-09-14}.sub(/.*/){|c| (Date.parse(c) == Date.today) ? c : raise("ERROR: s.date=(#{c}) is not today!")}
17
17
  s.summary = %q{Module to handle Plain-Text}
18
18
  s.description = %q{This module provides utility functions and methods to handle plain text, classes Part/Paragraph/Boundary to represent the logical structure of a document and ParseRule to describe the rules to parse plain text to produce a Part-type Ruby instance. A few handy Ruby executable scripts to make use of them are included.}
19
19
  # s.email = %q{abc@example.com}
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
41
41
  s.rdoc_options = ["--charset=UTF-8"]
42
42
 
43
43
  # s.require_paths = ["lib"] # Default "lib"
44
- s.required_ruby_version = '>= 2.0', '< 3.2'
44
+ s.required_ruby_version = '>= 2.0'
45
45
  s.test_files = Dir['test/**/*.rb']
46
46
  s.test_files.reject! { |fn| File.symlink? fn }
47
47
  # s.requirements << 'libmagick, v6.0' # Simply, info to users.
@@ -2,11 +2,26 @@
2
2
 
3
3
  # Author: M. Sakano (Wise Babel Ltd)
4
4
 
5
- require 'plain_text'
6
-
7
5
  $stdout.sync=true
8
6
  $stderr.sync=true
7
+
9
8
  # print '$LOAD_PATH=';p $LOAD_PATH
9
+ arlibbase = %w(plain_text)
10
+
11
+ arlibrelbase = arlibbase.map{|i| "../lib/"+i}
12
+
13
+ arlibrelbase.each do |elibbase|
14
+ require_relative elibbase
15
+ end # arlibbase.each do |elibbase|
16
+
17
+ print "NOTE: Running: "; p File.basename(__FILE__)
18
+ print "NOTE: Library relative paths: "; p arlibrelbase
19
+ arlibbase4full = arlibbase.map{|i| i.sub(%r@^(../)+@, "")}
20
+ puts "NOTE: Library full paths for #{arlibbase4full.inspect}: "
21
+ arlibbase4full.each do |elibbase|
22
+ ar = $LOADED_FEATURES.grep(/(^|\/)#{Regexp.quote(File.basename(elibbase))}(\.rb)?$/).uniq
23
+ print elibbase+": " if ar.empty?; p ar
24
+ end
10
25
 
11
26
  #################################################
12
27
  # Unit Test
@@ -2,12 +2,26 @@
2
2
 
3
3
  # Author: M. Sakano (Wise Babel Ltd)
4
4
 
5
- require 'plain_text'
6
- require 'plain_text/parse_rule'
7
-
8
5
  $stdout.sync=true
9
6
  $stderr.sync=true
7
+
10
8
  # print '$LOAD_PATH=';p $LOAD_PATH
9
+ arlibbase = %w(plain_text plain_text/parse_rule)
10
+
11
+ arlibrelbase = arlibbase.map{|i| "../lib/"+i}
12
+
13
+ arlibrelbase.each do |elibbase|
14
+ require_relative elibbase
15
+ end # arlibbase.each do |elibbase|
16
+
17
+ print "NOTE: Running: "; p File.basename(__FILE__)
18
+ print "NOTE: Library relative paths: "; p arlibrelbase
19
+ arlibbase4full = arlibbase.map{|i| i.sub(%r@^(../)+@, "")}
20
+ puts "NOTE: Library full paths for #{arlibbase4full.inspect}: "
21
+ arlibbase4full.each do |elibbase|
22
+ ar = $LOADED_FEATURES.grep(/(^|\/)#{Regexp.quote(File.basename(elibbase))}(\.rb)?$/).uniq
23
+ print elibbase+": " if ar.empty?; p ar
24
+ end
11
25
 
12
26
  #################################################
13
27
  # Unit Test
@@ -2,11 +2,27 @@
2
2
 
3
3
  # Author: M. Sakano (Wise Babel Ltd)
4
4
 
5
- require 'plain_text'
6
-
7
5
  $stdout.sync=true
8
6
  $stderr.sync=true
7
+
9
8
  # print '$LOAD_PATH=';p $LOAD_PATH
9
+ arlibbase = %w(plain_text)
10
+
11
+ arlibrelbase = arlibbase.map{|i| "../lib/"+i}
12
+
13
+ arlibrelbase.each do |elibbase|
14
+ require_relative elibbase
15
+ end # arlibbase.each do |elibbase|
16
+
17
+ print "NOTE: Running: "; p File.basename(__FILE__)
18
+ print "NOTE: Library relative paths: "; p arlibrelbase
19
+ arlibbase4full = arlibbase.map{|i| i.sub(%r@^(../)+@, "")}+%w(part part/paragraph part/boundary plain_text/util builtin_type part/string_type)
20
+ puts "NOTE: Library full paths for #{arlibbase4full.inspect}: "
21
+ arlibbase4full.each do |elibbase|
22
+ #ar = $LOADED_FEATURES.grep(/(^|\/)#{Regexp.quote(File.basename(elibbase))}(\.rb)?$/).uniq
23
+ ar = $LOADED_FEATURES.grep(/(^|\/)#{Regexp.quote(elibbase)}(\.rb)?$/).uniq
24
+ print elibbase+": " if ar.empty?; p ar
25
+ end
10
26
 
11
27
  #################################################
12
28
  # Unit Test
@@ -24,6 +40,15 @@ require 'minitest/autorun'
24
40
  require 'rubygems' if !defined? Gem # for Ruby 1
25
41
  IS_VER_2 = (Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3'))
26
42
 
43
+ # defines user-defined subclasses.
44
+ class PlainText::Part
45
+ class Section < self
46
+ class Subsection < self; end # It must be a child class!
47
+ end
48
+ end
49
+ class PlainText::Part::Boundary::MyA < PlainText::Part::Boundary
50
+ end
51
+
27
52
  class TestUnitPlainTextPart < MiniTest::Test
28
53
  T = true
29
54
  F = false
@@ -67,7 +92,7 @@ class TestUnitPlainTextPart < MiniTest::Test
67
92
  assert_equal a2[2], pt2[2]
68
93
  assert_equal ap2, pt2.paras
69
94
  assert_equal ab2, pt2.boundaries
70
- assert_equal a2+[""], pt2.to_a # An empty String is appended.
95
+ assert_equal a2+[""], pt2.to_a, "former=#{a2+['']} <=> #{pt2.to_a}" # An empty String is appended.
71
96
  assert_operator a2, '!=', pt2
72
97
  assert_operator pt2, '!=', a2
73
98
  end
@@ -82,12 +107,19 @@ class TestUnitPlainTextPart < MiniTest::Test
82
107
 
83
108
  pt11 = Pt.new(a1)
84
109
  pt12 = Pt.new(ap1, ab1)
85
- assert_equal pt11, pt12
110
+ assert_equal pt11, pt12, "pt11.inspect=#{pt11.inspect}"
86
111
  pt21 = Pt.new(a2)
87
112
  pt22 = Pt.new(ap2, ab2)
88
113
  assert_equal pt21, pt22
89
114
  end
90
115
 
116
+ def test_new03
117
+ assert_raises(ArgumentError){ Pt.new(?a) }
118
+ assert_raises(ArgumentError){ Pt.new(3) }
119
+ assert_raises(TypeError){ Pt.new([Pt::Boundary.new(""), Pt::Boundary.new("\n") ]) }
120
+ assert_raises(TypeError){ Pt.new([Pt::Paragraph.new(""), Pt::Paragraph.new("a")]) }
121
+ end
122
+
91
123
  def test_size2extract01
92
124
  a1 = ["a", "\n\n\n", "b", "\n\n\n", "c", "\n\n"]
93
125
  pt1 = Pt.new(a1)
@@ -113,7 +145,7 @@ class TestUnitPlainTextPart < MiniTest::Test
113
145
  assert_raises(IndexError){ pt1.send(:size2extract, (-9..-9), ignore_error: false, skip_renormalize: false) }
114
146
  end
115
147
 
116
-
148
+
117
149
  def test_equal01
118
150
  a1 = ["a", "\n\n\n", "b", "\n\n\n", "c", "\n\n"]
119
151
  pt1 = Pt.new(a1)
@@ -121,17 +153,31 @@ class TestUnitPlainTextPart < MiniTest::Test
121
153
  pt2 = Pt.new(a2)
122
154
 
123
155
  assert_operator pt1, '==', Pt.new(a1)
156
+ assert_operator pt1, '==', Pt.new(a1.dup)
157
+ assert_operator pt1, '==', Pt.new(pt1.deepcopy.to_a)
124
158
  assert_operator a1, '==', pt1.to_a
125
159
  assert_operator a1, '!=', pt1
126
160
  assert_operator pt1, '!=', a1
127
- assert_operator a1, '!=', ?a
128
- assert_operator ?a, '!=', a1
129
161
  assert_operator pt1, '!=', pt2
130
162
  assert_operator pt2, '!=', pt1
131
163
  assert_operator pt1, '!=', ?a
132
164
  assert_operator ?a, '!=', pt1
133
165
  end
134
166
 
167
+ def test_equal02_para_boundary
168
+ pa1 = Pt::Paragraph.new("abc")
169
+ bo1 = Pt::Boundary.new("\n\n")
170
+ assert_equal pa1, "abc"
171
+ assert_equal "abc", pa1
172
+ assert_equal pa1, Pt::Paragraph.new("abc")
173
+ assert_equal bo1, "\n\n"
174
+ assert_equal "\n\n", bo1
175
+ assert_equal bo1, Pt::Boundary.new("\n\n")
176
+
177
+ assert_respond_to pa1, :+
178
+ assert_respond_to bo1, :gsub!
179
+ end
180
+
135
181
  def test_nomethoderror01
136
182
  a1 = ["a", "\n\n\n", "b", "\n\n\n", "c", "\n\n"]
137
183
  pt1 = Pt.new(a1)
@@ -149,7 +195,7 @@ class TestUnitPlainTextPart < MiniTest::Test
149
195
  assert_equal a1+["d", ""], pt3.to_a
150
196
  assert_equal pt1.class, pt3.class
151
197
  assert_equal Pt.new(a3), pt3 # Boundary("") is appended.
152
- assert_equal Pt::Boundary, pt3.to_a[-1].class if IS_VER_2 # Not in Ruby 3 (see note at the top)
198
+ assert_equal Pt::Boundary, pt3.to_a[-1].class
153
199
  assert_equal pt3, pt1 + ["d", ""]
154
200
 
155
201
  assert_equal a3.class, ([]+pt3).class # The latter, too, is an Array (NOT PlainText::Part)
@@ -176,10 +222,11 @@ class TestUnitPlainTextPart < MiniTest::Test
176
222
  assert_nil pt1[-99]
177
223
  assert_nil pt1[98]
178
224
 
179
- assert_equal pt1.class, pt1[0, 6].class if IS_VER_2 # Not in Ruby 3 (see note at the top)
225
+ assert_equal pt1.class, pt1[0, 6].class
180
226
  assert_equal a1, pt1[0, 6].to_a
181
227
  assert_equal a1[0, 6], pt1[0, 6].to_a
182
- oper = (IS_VER_2 ? :!= : :==) # Because PlainText::Part#== is redefined and pt1 is Part in Ruby 2, the following is unequal, whereas pt1 is Array in Ruby 3!
228
+ # oper = (IS_VER_2 ? :!= : :==) # Because PlainText::Part#== is redefined and pt1 is Part in Ruby 2, the following is unequal, whereas pt1 is Array in Ruby 3!
229
+ oper = :!= # In Ver.0.8, it is redefined as unequal.
183
230
  assert_operator pt1[0, 6], oper, a1
184
231
  assert_operator a1, oper, pt1[0, 6]
185
232
 
@@ -187,7 +234,7 @@ class TestUnitPlainTextPart < MiniTest::Test
187
234
  assert_equal a1, pt1[0, 98].to_a
188
235
  assert_equal a1[0, 99], pt1[0, 98].to_a
189
236
 
190
- assert_equal pt1.class, pt1[0..1].class if IS_VER_2 # Not in Ruby 3 (see note at the top)
237
+ assert_equal pt1.class, pt1[0..1].class
191
238
  assert_equal a1[0..1], pt1[0..1].to_a
192
239
  assert_equal a1[0, 2], pt1[0..1].to_a
193
240
  assert_equal a1[0..5], pt1[0..5].to_a
@@ -202,14 +249,12 @@ class TestUnitPlainTextPart < MiniTest::Test
202
249
 
203
250
  assert_equal pt1[0..-1], pt1[0..99]
204
251
  assert_equal pt1[0, 6], pt1[0..-1]
205
- assert_equal pt1, pt1[0..99] if IS_VER_2 # Not in Ruby 3 (see note at the top)
252
+ assert_equal pt1, pt1[0..99]
206
253
 
207
- if IS_VER_2 # Not in Ruby 3 (see note at the top)
208
- pt2 = pt1[0, 4]
209
- assert_equal pt1.class, pt2.class
210
- assert_equal pt1.paras[0, 2], pt2.paras
211
- assert_equal pt1.boundaries[0, 2], pt2.boundaries
212
- end
254
+ pt2 = pt1[0, 4]
255
+ assert_equal pt1.class, pt2.class
256
+ assert_equal pt1.paras[0, 2], pt2.paras
257
+ assert_equal pt1.boundaries[0, 2], pt2.boundaries
213
258
 
214
259
  # negative or too-big out-of-bound begin
215
260
  assert_nil a1[-99..2]
@@ -218,7 +263,6 @@ class TestUnitPlainTextPart < MiniTest::Test
218
263
  assert_nil pt1[98..99]
219
264
 
220
265
  # other out-of-bounds: Empty
221
- assert_equal Pt.new([]), pt1[2..1] if IS_VER_2 # Not in Ruby 3 (see note at the top)
222
266
  assert_equal a1[-2..2], pt1[-2..2].to_a
223
267
  assert_equal a1[-2...3], pt1[-2...3].to_a
224
268
 
@@ -235,12 +279,10 @@ class TestUnitPlainTextPart < MiniTest::Test
235
279
  assert_nil pt1[pt1.size]
236
280
  assert_nil pt1[pt1.size, -2]
237
281
  assert_raises(TypeError){ pt1[pt1.size, ?a] }
238
- if IS_VER_2 # Not in Ruby 3 (see note at the top)
239
- assert_equal Pt.new([]), pt1[pt1.size, 2]
240
- assert_equal Pt.new([]), pt1[pt1.size, 98]
241
- assert_equal Pt.new([]), pt1[pt1.size..99]
242
- assert_equal Pt.new([]), pt1[pt1.size..1]
243
- end
282
+ assert_equal Pt.new([]), pt1[pt1.size, 2]
283
+ assert_equal Pt.new([]), pt1[pt1.size, 98]
284
+ assert_equal Pt.new([]), pt1[pt1.size..99]
285
+ assert_equal Pt.new([]), pt1[pt1.size..1]
244
286
  end
245
287
 
246
288
  # Tests of slice! to delete
@@ -261,12 +303,12 @@ class TestUnitPlainTextPart < MiniTest::Test
261
303
 
262
304
  assert_equal a11[4, 2], a1.slice!(4, 2)
263
305
  ptp = pt1.slice!(4, 2)
264
- assert_equal pt1.class, ptp.class if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part
306
+ assert_equal pt1.class, ptp.class
265
307
  assert_equal a11[4, 2], ptp.to_a
266
- assert_operator a11[4, 2], :!=, ptp if IS_VER_2 # PlainText::Part != Array
308
+ assert_operator a11[4, 2], :!=, ptp # PlainText::Part != Array
267
309
  assert_equal a11[0..3], a1
268
310
  assert_equal a11[0..3], pt1.to_a
269
- assert_equal pt2[0..3], pt1 if IS_VER_2 # Not in Ruby 3 (see note at the top)
311
+ assert_equal pt2[0..3], pt1
270
312
 
271
313
  # Negative size (Index, Size)
272
314
  a1 = a11.clone
@@ -282,9 +324,9 @@ class TestUnitPlainTextPart < MiniTest::Test
282
324
  pt1 = Pt.new(a11.clone)
283
325
  assert_equal a11[4, 6], a1.slice!(4, 6)
284
326
  ptp = pt1.slice!(4, 6)
285
- assert_equal pt1.class, ptp.class if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part
327
+ assert_equal pt1.class, ptp.class # PlainText::Part
286
328
  assert_equal a11[4, 2], ptp.to_a
287
- assert_operator a11[4, 2], :!=, ptp if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part != Array
329
+ assert_operator a11[4, 2], :!=, ptp # PlainText::Part != Array
288
330
  assert_equal a11[0..3], a1
289
331
 
290
332
  # Range exceeding (Range)
@@ -292,10 +334,10 @@ class TestUnitPlainTextPart < MiniTest::Test
292
334
  pt1 = Pt.new(a11.clone)
293
335
  assert_equal a11[4..9], a1.slice!(4..9)
294
336
  ptp = pt1.slice!(4..9)
295
- assert_equal pt1.class, ptp.class if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part
337
+ assert_equal pt1.class, ptp.class # PlainText::Part
296
338
  assert_equal a11[4..-1],ptp.to_a
297
339
  assert_equal a11[4..9], ptp.to_a
298
- assert_operator a11[4..9], :!=, ptp if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part != Array
340
+ assert_operator a11[4..9], :!=, ptp # PlainText::Part != Array
299
341
  assert_equal a11[0..3], a1
300
342
  assert_equal a11[0..3], pt1.to_a
301
343
 
@@ -315,9 +357,9 @@ class TestUnitPlainTextPart < MiniTest::Test
315
357
  pt1 = Pt.new(a11.clone)
316
358
  assert_equal a11[-6, 2], a1.slice!(-6, 2)
317
359
  ptp = pt1.slice!(-6, 2)
318
- assert_equal pt1.class, ptp.class if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part
360
+ assert_equal pt1.class, ptp.class # PlainText::Part
319
361
  assert_equal a11[0..1], ptp.to_a
320
- assert_operator a11[0..1], :!=, ptp if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part != Array
362
+ assert_operator a11[0..1], :!=, ptp # PlainText::Part != Array
321
363
  assert_equal a11[2..-1], a1
322
364
  assert_equal a11[2..-1], pt1.to_a
323
365
 
@@ -326,9 +368,9 @@ class TestUnitPlainTextPart < MiniTest::Test
326
368
  pt1 = Pt.new(a11.clone)
327
369
  assert_equal a11[-6..-5], a1.slice!(-6..-5)
328
370
  ptp = pt1.slice!(-6..-5)
329
- assert_equal pt1.class, ptp.class if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part
371
+ assert_equal pt1.class, ptp.class # PlainText::Part
330
372
  assert_equal a11[0..1], ptp.to_a
331
- assert_operator a11[0..1], :!=, ptp if IS_VER_2 # Not in Ruby 3 (see note at the top) # PlainText::Part != Array
373
+ assert_operator a11[0..1], :!=, ptp # PlainText::Part != Array
332
374
  assert_equal a11[2..-1], a1
333
375
  assert_equal a11[2..-1], pt1.to_a
334
376
 
@@ -355,48 +397,56 @@ class TestUnitPlainTextPart < MiniTest::Test
355
397
  assert_equal "b\n\n", pt1[2..3].join
356
398
 
357
399
  pt2 = pt1.dup
400
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
358
401
  pt2.merge_para!(2,3,4)
359
402
  assert_equal s1, pt2.join
360
403
  assert_equal 8, pt2.size
361
404
  assert_equal "b\n\nc\n\n", pt2[2..3].join
362
405
 
363
406
  pt2 = pt1.dup
407
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
364
408
  pt2.merge_para!(2,3,4, 5)
365
409
  assert_equal s1, pt2.join
366
- assert_equal 8, pt2.size
410
+ assert_equal 8, pt2.size, "Size should be 8: pt2="+pt2.inspect
367
411
  assert_equal "b\n\nc\n\n", pt2[2..3].join
368
412
 
369
413
  pt2 = pt1.dup
414
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
370
415
  pt2.merge_para!(2..4)
371
416
  assert_equal s1, pt2.join
372
417
  assert_equal 8, pt2.size
373
418
  assert_equal "b\n\nc\n\n", pt2[2..3].join
374
419
 
375
420
  pt2 = pt1.dup
421
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
376
422
  pt2.merge_para!(2..5)
377
423
  assert_equal s1, pt2.join
378
424
  assert_equal 8, pt2.size
379
425
  assert_equal "b\n\nc\n\n", pt2[2..3].join
380
426
 
381
427
  pt2 = pt1.dup
428
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
382
429
  pt2.merge_para!(2...6)
383
430
  assert_equal s1, pt2.join
384
431
  assert_equal 8, pt2.size
385
432
  assert_equal "b\n\nc\n\n", pt2[2..3].join
386
433
 
387
434
  pt2 = pt1.dup
435
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
388
436
  pt2.merge_para!(2...-4)
389
437
  assert_equal s1, pt2.join
390
438
  assert_equal 8, pt2.size
391
439
  assert_equal "b\n\nc\n\n", pt2[2..3].join
392
440
 
393
441
  pt2 = pt1.dup
442
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
394
443
  pt2.merge_para!(1..2, use_para_index: true)
395
444
  assert_equal s1, pt2.join
396
445
  assert_equal 8, pt2.size
397
446
  assert_equal "b\n\nc\n\n", pt2[2..3].join
398
447
 
399
448
  pt2 = pt1.dup
449
+ assert_equal 10, pt2.size, "Sanity check should pass: #{pt2.inspect}"
400
450
  pt2.merge_para!(8..12)
401
451
  assert_equal s1, pt2.join
402
452
  assert_equal 10, pt2.size
@@ -407,7 +457,7 @@ class TestUnitPlainTextPart < MiniTest::Test
407
457
  s1 = "a\n\nb\n\nc\n\nd\n\ne\n\n"
408
458
  # 0 1 2 3 4 5 6 7 8 9
409
459
  pt1 = Pt.parse s1
410
-
460
+
411
461
  pt2 = pt1.dup
412
462
  assert pt2.merge_para_if{|ary,bi,bf|
413
463
  ary[0] == ?b && ary[2] == ?c
@@ -438,9 +488,127 @@ class TestUnitPlainTextPart < MiniTest::Test
438
488
  assert_equal s1, pt1.join
439
489
  end
440
490
 
491
+ # subclass_name defined in /lib/plain_text/builtin_type.rb
492
+ def test_subclass_name
493
+ bo1 = Pt::Boundary::MyA.new("\n===\n")
494
+ assert_equal "Part::Boundary::MyA", bo1.subclass_name
495
+ assert_equal "Boundary::MyA", bo1.subclass_name(index_ini: 1)
496
+ assert_equal "MyA", bo1.subclass_name(index_ini: 2)
497
+
498
+ ss = PlainText::Part::Section::Subsection.new ["abc"]
499
+ assert_equal "Part::Section::Subsection", ss.subclass_name
500
+ assert_equal "Section::Subsection", ss.subclass_name(index_ini: 1)
501
+ end
502
+
503
+ def test_dup
504
+ pa1 = Pt::Paragraph.new("b")
505
+ bo1 = Pt::Boundary::MyA.new("\n===\n")
506
+ para1 = [Pt::Paragraph.new("a"), pa1, Pt::Paragraph.new("c")]
507
+ boun1 = [Pt::Boundary.new("\n"), bo1, Pt::Boundary.new("\n")]
508
+ pt1 = Pt.new(para1, boun1)
509
+ assert_equal pt1[2], pa1
510
+ refute_equal pt1[2].object_id, pa1.object_id, "New one should be given a different object_id (unicode_normalized)"
511
+
512
+ pt2 = pt1.dup
513
+ refute_equal pt1.object_id, pt2.object_id
514
+ refute_equal pt1.instance.object_id, pt2.instance.object_id
515
+ assert_equal pt1[2].object_id, pt2[2].object_id
516
+ assert_equal pt1.paras[1].object_id, pt2[2].object_id
517
+ assert_equal pt1.paras[1].object_id, pt2.paras[1].object_id
518
+ assert_equal pt1.boundaries[1].object_id, pt2.boundaries[1].object_id
519
+
520
+ pa2 = pa1.dup
521
+ assert_equal pa1, pa2
522
+ refute_equal pa1.object_id, pa2.object_id
523
+ refute_equal pa1.instance.object_id, pa2.instance.object_id
524
+ pa2.replace("x")
525
+ refute_equal pa1, pa2
526
+
527
+ bo2 = bo1.dup
528
+ assert_equal bo1, bo2
529
+ refute_equal bo1.object_id, bo2.object_id
530
+ refute_equal bo1.instance.object_id, bo2.instance.object_id
531
+ bo2.replace("x")
532
+ refute_equal bo1, bo2
533
+ end
534
+
535
+ def test_deepcopy
536
+ para1 = [Pt::Paragraph.new("a"), Pt::Paragraph.new("b"), Pt::Paragraph.new("c")]
537
+ boun1 = [Pt::Boundary.new("\n"), Pt::Boundary::MyA.new("\n===\n"), Pt::Boundary.new("\n")]
538
+ pt1 = Pt.new(para1, boun1)
539
+ pt2 = pt1.deepcopy
540
+ assert_equal pt1, pt2
541
+ assert_equal Pt::Paragraph, pt1.to_a[0].class
542
+ assert_equal Pt::Boundary, pt1.to_a[1].class
543
+ assert_equal Pt::Paragraph, pt1.to_a[2].class
544
+ assert_equal Pt::Boundary::MyA, pt1.to_a[3].class
545
+ assert_equal "Part::Boundary::MyA", pt1.to_a[3].subclass_name, "subclass_name should be equal: pt1: #{pt1.to_a[3].inspect}"
546
+ assert_equal "Part::Boundary::MyA", pt2.to_a[3].subclass_name
547
+ refute_equal pt1.object_id, pt2.object_id
548
+ refute_equal pt1.to_a[3].object_id, pt2.to_a[3].object_id
549
+ refute_equal pt1.to_a[3].to_s.object_id, pt2.to_a[3].to_s.object_id
550
+ refute_equal pt1.to_a[4].object_id, pt2.to_a[4].object_id
551
+ refute_equal pt1.to_a[4].to_s.object_id, pt2.to_a[4].to_s.object_id
552
+ end
553
+
554
+ def test_insert
555
+ a1 = ["a", "\n\n\n", "b", "\n\n\n", "c"]
556
+ pt1 = Pt.new(a1)
557
+ assert_equal 6, pt1.size, "Sanity check 1"
558
+ assert_equal a1+[""], pt1.to_a, "Sanity check 2"
559
+ pt2 = pt1.deepcopy
560
+ err = assert_raises(IndexError){ pt2.insert(-99, ?d, "\n") }
561
+ assert_raises(IndexError){ pt2.insert(-99) }
562
+ assert_match(/\btoo small for array\b/i, err.message)
563
+ assert_raises(IndexError){ pt2.insert(7, ?d, "\n") }
564
+ assert_raises(ArgumentError){ pt2.insert(-1, ?d) }
565
+ assert_raises(ArgumentError){ pt2.concat([?d]) }
566
+ assert_raises(ArgumentError){ pt2.push( ?d) }
567
+ assert_raises(ArgumentError){ pt2.insert(-1, ?d, "", ?e) }
568
+ assert_raises(TypeError){ pt2.insert(-1, Pt::Boundary.new("\n"), Pt::Paragraph.new(?d)) }
569
+ assert_raises(TypeError){ pt2.insert(-1, Pt::Paragraph.new(?d), Pt::Paragraph.new(?d)) }
570
+ assert_raises(TypeError){ pt2.insert(-2, Pt::Paragraph.new(?d), Pt::Boundary.new("\n")) }
571
+ assert_raises(TypeError){ pt2.insert(-2, Pt::Boundary.new("\n"), Pt::Boundary.new("\n")) }
572
+ assert_raises(TypeError){ pt2.insert(-2, Pt.new([?d]), Pt::Boundary.new("\n")) }
573
+ pt2 = pt1.deepcopy # required, as @array is altered.
574
+ assert_equal pt1, pt2
575
+ assert_equal pt1, pt2.insert(-1), "Insert with no second arguments should alter nothing."
576
+ assert_equal pt1, pt2.insert(0)
577
+ assert_equal pt1, pt2.insert(1)
578
+
579
+ pt2.insert(-1, ?e, "\n")
580
+ assert_equal 8, pt2.size
581
+ assert_equal [?e, "\n"], pt2.to_a[-2..-1]
582
+ assert pt2[-2].paragraph?
583
+ assert pt2[-1].boundary?
584
+
585
+ bo5 = Pt::Boundary.new("==")
586
+ pt2.insert(5, bo5, ?d)
587
+ assert_equal 10, pt2.size
588
+ assert_equal ["==", ?d, "", ?e, "\n"], pt2.to_a[-5..-1]
589
+ assert pt2[-2].paragraph?
590
+ assert pt2[-1].boundary?
591
+ assert_equal bo5, pt2[5]
592
+ assert pt2[5].boundary?
593
+ assert_equal "d", pt2[6]
594
+ assert pt2[6].paragraph?
595
+
596
+ pt2.insert(2, pt1, "")
597
+ assert_equal 12, pt2.size
598
+ assert_equal "a\n\n\na\n\n\nb\n\n\ncb\n\n\nc==de\n", pt2.join
599
+ end
600
+
601
+ def test_array_methods
602
+ a1 = ["a", "\n\n\n", "b", "\n\n\n", "c"]
603
+ pt1 = Pt.new(a1)
604
+ assert_equal 6, pt1.size
605
+ assert_equal a1+[""], pt1.to_a
606
+ assert_raises(NoMethodError){ pt1.delete_at(0) }
607
+ assert_raises(NoMethodError){ pt1 << ?d }
608
+ end
609
+
441
610
  #assert ( /_rails_db\.sql$/ =~ s1.outfile )
442
611
  #assert_nil fkeys
443
- #assert_match(/^\s*ADD CONSTRAINT/ , s1.instance_eval{ @strall })
444
612
  end # class TestUnitPlainTextPart < MiniTest::Test
445
613
 
446
614
  #end # if $0 == __FILE__