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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/ChangeLog +11 -0
- data/Makefile +2 -1
- data/README.en.rdoc +67 -61
- data/lib/plain_text/builtin_type.rb +64 -0
- data/lib/plain_text/error.rb +6 -0
- data/lib/plain_text/part/boundary.rb +38 -28
- data/lib/plain_text/part/paragraph.rb +41 -18
- data/lib/plain_text/part/string_type.rb +90 -0
- data/lib/plain_text/part.rb +316 -275
- data/lib/plain_text/util.rb +13 -12
- data/lib/plain_text.rb +14 -10
- data/plain_text.gemspec +3 -3
- data/test/test_plain_text.rb +17 -2
- data/test/test_plain_text_parse_rule.rb +17 -3
- data/test/test_plain_text_part.rb +207 -39
- data/test/test_plain_text_split.rb +17 -2
- data/test/test_plain_text_util.rb +17 -2
- metadata +5 -5
data/lib/plain_text/util.rb
CHANGED
@@ -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
|
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
|
69
|
-
def positive_array_index(i,
|
70
|
-
arysize = (
|
71
|
-
i2 = i.to_int rescue (raise TypeError, sprintf("no implicit conversion of #{i.class} into Integer (i=#{i.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
|
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
|
91
|
-
def positive_array_index_checked(index_in,
|
92
|
-
# def self.positive_valid_index_for_array(index_in,
|
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 = (
|
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
|
-
#
|
12
|
-
#
|
13
|
-
#
|
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.
|
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
|
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
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
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.
|
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-
|
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'
|
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.
|
data/test/test_plain_text.rb
CHANGED
@@ -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
|
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
|
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
|
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]
|
252
|
+
assert_equal pt1, pt1[0..99]
|
206
253
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
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
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
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
|
306
|
+
assert_equal pt1.class, ptp.class
|
265
307
|
assert_equal a11[4, 2], ptp.to_a
|
266
|
-
assert_operator a11[4, 2], :!=, ptp
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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__
|