scripref 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a2bd9fe1cbf211fb440e24443090c3491e9ec0b
4
- data.tar.gz: d6e4bd60dd77a8aa63eef39cb4ee777a2315c4ed
3
+ metadata.gz: 605d0d995b512d6af69e3b2152228dc201085b2b
4
+ data.tar.gz: a400e265c6d777d287170fbef3edb56c0143fcc6
5
5
  SHA512:
6
- metadata.gz: b43ac2c70d71ba2420d6dadfe9abe6ae8bcad9b4914c2420d7337fe5bdfe7e11f8ac730042830fd4eff18e76a7e6f3f3e0cc2e58c7caa79b3cd81395e4383cc5
7
- data.tar.gz: 9e5b4035b11fbf2305edd243fa703be3b54f8cd0a55ad074737b6a9e9dc63edd1412f3c4272ae074bcd20e6c30b7fb6e3c0215f84738c7d6696646b1437e60a1
6
+ metadata.gz: 37506e93da2d733beaa800db74ef5d1f16fe7aee313312298752a3f442549434b5360646b62d7d754dc189efa6edf1b09372be04b0a85e8f39dca290f2082b1a
7
+ data.tar.gz: 1e74214d77ed1f74256c102ea448eba2ba703d90269dc697360494dee102900d9f2503c8310f95ce783d1c92512a9eacba62e734adb8e411729d28dacccf3f98
@@ -1,3 +1,12 @@
1
+ 0.10.0
2
+ Add methods Passage#make_comparable, #make_comparable!, #comparable?,
3
+ #overlap?, #start, #end and #<=>.
4
+ Implement formatting of more than one passage with formatter.
5
+ Allow passage separator after ranges of books and chapters.
6
+ Add tests and fixing bugs.
7
+ Doing a lot of internal refactorings.
8
+ Add documentation.
9
+
1
10
  0.9.1
2
11
  Add Philemon to book with only one chapter.
3
12
 
@@ -1,6 +1,7 @@
1
1
  # - encoding: utf-8 -
2
2
  require 'delegate'
3
3
  require 'scripref/parser'
4
+ require 'scripref/passage'
4
5
  require 'scripref/processor'
5
6
  require 'scripref/formatter'
6
7
  require 'scripref/english'
@@ -8,35 +9,25 @@ require 'scripref/german'
8
9
 
9
10
  module Scripref
10
11
 
11
- VERSION = '0.9.1'
12
+ VERSION = '0.10.0'
12
13
 
13
- Passage = Struct.new(:text, :b1, :c1, :v1, :b2, :c2, :v2, :a1, :a2) do
14
-
15
- include Comparable
16
-
17
- def initialize text, b1, c1, v1, b2, c2, v2, opts={}
18
- super text, b1, c1, v1, b2, c2, v2, opts[:a1], opts[:a2]
19
- end
20
-
21
- def to_a
22
- [b1, c1, v1, b2, c2, v2]
14
+ class Token < DelegateClass(String)
15
+ def initialize *args
16
+ super
23
17
  end
18
+ end
24
19
 
25
- def <=> o
26
- a1 = self.to_a.map {|e| e.nil? ? 0 : e}
27
- a2 = o.to_a.map {|e| e.nil? ? 0 : e}
28
- a1 <=> a2
29
- end
20
+ class Book < Token; end
21
+ class Chapter < Token; end
22
+ class Verse < Token; end
30
23
 
31
- alias to_s text
32
- end
24
+ class Addon < Token; end
25
+ class Postfix < Token; end
33
26
 
34
- class Sep < DelegateClass(String)
35
- def initialize s
36
- super s
37
- end
38
- end
27
+ class Sep < Token; end
39
28
  class PassSep < Sep; end
40
29
  class VerseSep < Sep; end
41
30
 
31
+ class Space < Token; end
32
+
42
33
  end
@@ -42,6 +42,9 @@ module Scripref
42
42
  # Regular expression to match a separator between verses.
43
43
  VERSE_SEP_RE = /,\s*/o
44
44
 
45
+ # Separator between verses.
46
+ VERSE_SEPARATOR = ','
47
+
45
48
  # Regular expression to match addons for a verse.
46
49
  VERSE_ADDON_RE = /[ab]\s*/o
47
50
 
@@ -16,20 +16,41 @@ module Scripref
16
16
  # Formats a reference (array of passages)
17
17
  def format *reference
18
18
  @last_b = @last_c = @last_v = :undefined
19
- @result = ''
20
- reference.flatten.each do |pass|
21
- @pass = pass
19
+ @result = []
20
+ reference.flatten.each do |entry|
21
+ next if entry.kind_of? Sep
22
+ @pass = entry
22
23
  process_passage
23
24
  end
24
- @result
25
+ @result.join
25
26
  end
26
27
 
27
28
  def format_book num
28
29
  Array(book_names[num - 1]).first
29
30
  end
30
31
 
32
+ def format_chapter num
33
+ num.to_s
34
+ end
35
+
36
+ def format_verse num
37
+ num.to_s
38
+ end
39
+
40
+ def format_addon a
41
+ a.to_s
42
+ end
43
+
44
+ def format_postfix p
45
+ p.to_s
46
+ end
47
+
31
48
  private
32
49
 
50
+ def last_token
51
+ @result.last
52
+ end
53
+
33
54
  def process_passage
34
55
  @changed = false
35
56
  process_b1
@@ -38,7 +59,11 @@ module Scripref
38
59
  def process_b1
39
60
  b1 = @pass.b1
40
61
  if @last_b != b1
41
- @result << format_book(b1)
62
+ case last_token
63
+ when Token
64
+ push_sep pass_separator
65
+ end
66
+ push_book b1
42
67
  @last_b = b1
43
68
  @changed = true
44
69
  end
@@ -48,9 +73,14 @@ module Scripref
48
73
  def process_c1
49
74
  c1 = @pass.c1
50
75
  if c1 && (@changed || @last_c != c1)
51
- @result << ' '
52
76
  if ! book_has_only_one_chapter?(@pass.b1)
53
- @result << c1.to_s
77
+ case last_token
78
+ when Book
79
+ push_space
80
+ when Token
81
+ push_sep pass_separator
82
+ end
83
+ push_chapter c1
54
84
  end
55
85
  @last_c = c1
56
86
  @changed = true
@@ -62,9 +92,16 @@ module Scripref
62
92
  v1 = @pass.v1
63
93
  if v1 && (@changed || @last_v != v1)
64
94
  if ! book_has_only_one_chapter?(@pass.b1)
65
- @result << cv_separator
95
+ case last_token
96
+ when Verse
97
+ push_sep verse_separator
98
+ when Token
99
+ push_sep cv_separator
100
+ end
101
+ else
102
+ push_space
66
103
  end
67
- @result << v1.to_s
104
+ push_verse v1
68
105
  @last_v = v1
69
106
  process_a1
70
107
  end
@@ -73,7 +110,7 @@ module Scripref
73
110
 
74
111
  def process_a1
75
112
  a1 = @pass.a1
76
- @result << a1.to_s if a1
113
+ push_addon a1
77
114
  end
78
115
 
79
116
  def process_b2
@@ -81,8 +118,8 @@ module Scripref
81
118
  @hyphen = false
82
119
  b2 = @pass.b2
83
120
  if b2 && (@changed || @last_b != b2)
84
- @result << hyphen_separator
85
- @result << format_book(b2)
121
+ push_sep hyphen_separator
122
+ push_book(b2)
86
123
  @last_b = b2
87
124
  @changed = true
88
125
  @hyphen = true
@@ -94,13 +131,13 @@ module Scripref
94
131
  c2 = @pass.c2
95
132
  if c2 && (@changed || @last_c != c2)
96
133
  if @hyphen
97
- @result << ' '
134
+ push_space
98
135
  else
99
- @result << hyphen_separator
136
+ push_sep hyphen_separator
100
137
  @hyphen = true
101
138
  end
102
139
  if ! book_has_only_one_chapter?(@pass.b2)
103
- @result << c2.to_s
140
+ push_chapter c2
104
141
  end
105
142
  @last_c = c2
106
143
  @changed = true
@@ -112,22 +149,22 @@ module Scripref
112
149
  v2 = @pass.v2
113
150
  case v2
114
151
  when :f
115
- @result << postfix_one_following_verse
152
+ push_postfix postfix_one_following_verse
116
153
  return
117
154
  when :ff
118
- @result << postfix_more_following_verses
155
+ push_postfix postfix_more_following_verses
119
156
  return
120
157
  end
121
158
  if v2 && (@changed || @last_v != v2)
122
159
  if @hyphen
123
160
  if ! book_has_only_one_chapter?(@pass.b2)
124
- @result << cv_separator
161
+ push_sep cv_separator
125
162
  end
126
163
  else
127
- @result << hyphen_separator
164
+ push_sep hyphen_separator
128
165
  @hyphen = true
129
166
  end
130
- @result << v2.to_s
167
+ push_verse v2
131
168
  @last_v = @v2
132
169
  @changed = true
133
170
  process_a2
@@ -136,7 +173,37 @@ module Scripref
136
173
 
137
174
  def process_a2
138
175
  a2 = @pass.a2
139
- @result << a2.to_s if a2
176
+ push_addon a2
177
+ end
178
+
179
+ def push_book b
180
+ @result << Book.new(format_book(b))
181
+ end
182
+
183
+ def push_chapter c
184
+ @result << Chapter.new(format_chapter(c))
185
+ end
186
+
187
+ def push_verse v
188
+ @result << Verse.new(format_verse(v))
189
+ end
190
+
191
+ def push_addon a
192
+ if a
193
+ @result << Addon.new(format_addon(a))
194
+ end
195
+ end
196
+
197
+ def push_postfix p
198
+ @result << Postfix.new(format_postfix(p))
199
+ end
200
+
201
+ def push_space
202
+ @result << Space.new(' ')
203
+ end
204
+
205
+ def push_sep s
206
+ @result << Sep.new(s)
140
207
  end
141
208
 
142
209
  alias << format
@@ -39,6 +39,9 @@ module Scripref
39
39
  # Regular expression to match a separator between verses.
40
40
  VERSE_SEP_RE = /\.\s*/o
41
41
 
42
+ # Separator between verses.
43
+ VERSE_SEPARATOR = '.'
44
+
42
45
  # Regular expression to match addons for a verse.
43
46
  VERSE_ADDON_RE = /[ab]\s*/o
44
47
 
@@ -52,8 +52,11 @@ module Scripref
52
52
  s = scan(book_re) or return nil
53
53
  @text << s
54
54
  @b1 = @b2 = abbrev2num(s)
55
+ @c1 = @v1 = @c2 = @v2 = nil
55
56
 
56
- if check(Regexp.new(chapter_re.source + cv_sep_re.source))
57
+ if pass_sep
58
+ b1 or give_up 'EOS or book expected!'
59
+ elsif check(Regexp.new(chapter_re.source + cv_sep_re.source))
57
60
  @c1 = @v1 = nil
58
61
  @c2 = @v2 = nil
59
62
  c1
@@ -74,6 +77,7 @@ module Scripref
74
77
  s = scan(chapter_re) or return nil
75
78
  @text << s
76
79
  @c1 = @c2 = s.to_i
80
+ @v1 = @v2 = nil
77
81
 
78
82
  if cv_sep
79
83
  v1 or give_up 'Verse expected!'
@@ -123,14 +127,16 @@ module Scripref
123
127
  @b2 = abbrev2num(s)
124
128
  @c2 = @v2 = nil
125
129
 
126
- if check(Regexp.new(chapter_re.source + cv_sep_re.source))
130
+ if pass_sep
131
+ b1 or give_up 'EOS or book expected!'
132
+ elsif check(Regexp.new(chapter_re.source + cv_sep_re.source))
127
133
  c2
128
134
  else
129
135
  if book_has_only_one_chapter?(@b2)
130
136
  @c2 = 1
131
137
  epsilon or v2 or give_up 'EOS or chapter or verse expected!'
132
138
  else
133
- epsilon or c2 or ('EOS or chapter expected')
139
+ epsilon or c2 or give_up 'EOS or chapter expected!'
134
140
  end
135
141
  end
136
142
  end
@@ -143,6 +149,8 @@ module Scripref
143
149
 
144
150
  if cv_sep
145
151
  v2 or give_up 'Verse expected!'
152
+ elsif pass_sep
153
+ b1 or c1 or give_up 'Book or chapter expected!'
146
154
  else
147
155
  epsilon or give_up 'EOS or chapter verse separator expected!'
148
156
  end
@@ -0,0 +1,76 @@
1
+ # - encoding: utf-8 -
2
+ module Scripref
3
+
4
+ Passage = Struct.new(:text, :b1, :c1, :v1, :b2, :c2, :v2, :a1, :a2) do
5
+
6
+ include Comparable
7
+
8
+ def initialize text, b1, c1, v1, b2, c2, v2, a1: nil, a2: nil
9
+ super text, b1, c1, v1, b2, c2, v2, a1, a2
10
+ end
11
+
12
+ def to_a
13
+ [b1, c1, v1, b2, c2, v2]
14
+ end
15
+
16
+ def <=> other
17
+ return unless other.kind_of? Passage
18
+ self.make_comparable.to_a <=> other.make_comparable.to_a
19
+ end
20
+
21
+ # Returns a copy which is comparable, that means
22
+ # all values are numeric.
23
+ # This is a heuristic approach.
24
+ def make_comparable max: 999, ff: 3
25
+ self.dup.make_comparable! max: max, ff: ff
26
+ end
27
+
28
+ # Makes the Passage instance comparable, that means
29
+ # all values are numeric.
30
+ # This is a heuristic approach.
31
+ def make_comparable! max: 999, ff: 3
32
+ self.b1 ||= 1
33
+ self.c1 ||= 1
34
+ self.v1 ||= 1
35
+ self.b2 ||= max
36
+ self.c2 ||= max
37
+ self.v2 ||= max
38
+ if self.v2 == :f
39
+ self.v2 = self.v1 + 1
40
+ end
41
+ if self.v2 == :ff
42
+ self.v2 = self.v1 + ff
43
+ end
44
+ self
45
+ end
46
+
47
+ # Checks if the instance is comparable, that means
48
+ # all values are numeric and so the <=> method
49
+ # can be applied.
50
+ def comparable?
51
+ to_a.map {|e| Numeric === e}.uniq == [true]
52
+ end
53
+
54
+ # Returns true if the instance and the given passage overlap.
55
+ # That means both has at least one verse in common.
56
+ def overlap? passage
57
+ fail ArgumentError, 'value must be a passage' unless passage.kind_of? Passage
58
+ a = self.make_comparable.to_a
59
+ b = passage.make_comparable.to_a
60
+ [a[0..2] <=> b[3..5], b[0..2] <=> a[3..5]].max < 1
61
+ end
62
+
63
+ # Returns an array of b1, c1, v1
64
+ def start
65
+ [b1, c1, v1]
66
+ end
67
+
68
+ # Returns an array of b2, c2, v2
69
+ def end
70
+ [b2, c2, v2]
71
+ end
72
+
73
+ alias to_s text
74
+ end
75
+
76
+ end
@@ -340,10 +340,10 @@ result:
340
340
  - :text: '4'
341
341
  :b1: 8
342
342
  :c1: 4
343
- :v1: 9
343
+ :v1:
344
344
  :b2: 8
345
345
  :c2: 4
346
- :v2: 12
346
+ :v2:
347
347
  :a1:
348
348
  :a2:
349
349
  - "; "
@@ -369,9 +369,9 @@ result:
369
369
  ---
370
370
  sample: Ruth 2,1a-11.15a; 3,7b.9-12b; Markus ; 5,3a.18b-21a
371
371
  exception: |-
372
- EOS or hyphen and book or chapter expected!
372
+ EOS or book expected!
373
373
  Ruth 2,1a-11.15a; 3,7b.9-12b; Markus ; 5,3a.18b-21a
374
- ^
374
+ ^
375
375
  ---
376
376
  sample: Ruth 2,1a-11.15a; 3,7b.9-12b; Markus 45,3a.18b-21a
377
377
  result:
@@ -18,126 +18,248 @@ class TestFormatter < Test::Unit::TestCase
18
18
  end
19
19
 
20
20
  def test_only_book
21
- @german = 'Römer'
22
- @english = 'Romans'
23
- check_formatting
21
+ text = 'Ruth'
22
+ assert_formated_text_for_ast text, [pass(text, 8, nil, nil, 8, nil, nil)]
24
23
  end
25
24
 
26
25
  def test_book_and_chapter
27
- @german = 'Römer 8'
28
- @english = 'Romans 8'
29
- check_formatting
26
+ text = 'Ruth 2'
27
+ assert_formated_text_for_ast text, [pass(text, 8, 2, nil, 8, 2, nil)]
30
28
  end
31
29
 
32
- def test_one_verse
33
- @german = 'Römer 6,23'
34
- @english = 'Romans 6:23'
35
- check_formatting
30
+ def test_book_chapter_and_verse
31
+ text = 'Ruth 2,5'
32
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, 5)]
36
33
  end
37
34
 
38
- def test_book_range
39
- @german = 'Römer-Hebräer'
40
- @english = 'Romans-Hebrews'
41
- check_formatting
35
+ def test_verse_range
36
+ text = 'Ruth 2,5-11'
37
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, 11)]
38
+ end
39
+
40
+ def test_chapter_verse_range
41
+ text = 'Ruth 2,5-3,7'
42
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 3, 7)]
42
43
  end
43
44
 
44
45
  def test_chapter_range
45
- @german = 'Römer 1-8'
46
- @english = 'Romans 1-8'
47
- check_formatting
46
+ text = 'Ruth 2-3'
47
+ assert_formated_text_for_ast text, [pass(text, 8, 2, nil, 8, 3, nil)]
48
+ end
49
+
50
+ def test_book_range
51
+ text = '1. Mose-Offenbarung'
52
+ assert_formated_text_for_ast text, [pass(text, 1, nil, nil, 66, nil, nil)]
53
+ end
54
+
55
+ def test_book_chapter_range
56
+ text = '1. Mose 1-Offenbarung 22'
57
+ assert_formated_text_for_ast text, [pass(text, 1, 1, nil, 66, 22, nil)]
58
+ end
59
+
60
+ def test_book_chapter_verse_range
61
+ text = '1. Mose 1,1-Offenbarung 22,21'
62
+ assert_formated_text_for_ast text, [pass(text, 1, 1, 1, 66, 22, 21)]
63
+ end
64
+
65
+ def test_one_following_verse
66
+ text = 'Ruth 2,5f'
67
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, :f)]
68
+ end
69
+
70
+ def test_more_following_verse
71
+ text = 'Ruth 2,5ff'
72
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, :ff)]
48
73
  end
49
74
 
50
- def test_simple_passage
51
- @german = 'Römer 8,1-10'
52
- @english = 'Romans 8:1-10'
53
- check_formatting
75
+ def test_first_addon
76
+ text = 'Ruth 2,5a'
77
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, 5, a1: :a)]
54
78
  end
55
79
 
56
- def test_passage_with_chapter_change
57
- @german = 'Römer 1,1-5,11'
58
- @english = 'Romans 1:1-5:11'
59
- check_formatting
80
+ def test_second_addon
81
+ text = 'Ruth 2,5-7a'
82
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, 7, a2: :a)]
60
83
  end
61
84
 
62
- def test_passage_with_book_change
63
- @german = '1. Korinther 1,1-2. Korinther 13,13'
64
- @english = '1 Corinthians 1:1-2 Corinthians 13:13'
65
- check_formatting
85
+ def test_both_addons
86
+ text = 'Ruth 2,5b-7a'
87
+ assert_formated_text_for_ast text, [pass(text, 8, 2, 5, 8, 2, 7, a1: :b, a2: :a)]
66
88
  end
67
89
 
68
- def test_passage_with_different_chapter_and_same_verse
69
- @german = '2. Petrus 1,13-2,13'
70
- @english = '2 Peter 1:13-2:13'
71
- check_formatting
90
+ def test_reset_addons
91
+ @parser.parse 'Ruth 2,5b-7a'
92
+ text = 'Ruth'
93
+ assert_formated_text_for_ast text, [pass(text, 8, nil, nil, 8, nil, nil)]
72
94
  end
73
95
 
74
96
  def test_book_with_only_one_chapter
75
- @german = 'Obadja 3'
76
- @english = 'Obadiah 3'
77
- check_formatting
97
+ text = 'Obadja 3'
98
+ assert_formated_text_for_ast text, [pass(text, 31, 1, 3, 31, 1, 3)]
99
+ text = 'Obadja 1'
100
+ assert_formated_text_for_ast text, [pass(text, 31, 1, 1, 31, 1, 1)]
78
101
  end
79
102
 
80
103
  def test_book_with_only_one_chapter_range
81
- @german = 'Obadja 3-5'
82
- @english = 'Obadiah 3-5'
83
- check_formatting
104
+ text = 'Obadja 3-5'
105
+ assert_formated_text_for_ast text, [pass(text, 31, 1, 3, 31, 1, 5)]
106
+ text = 'Obadja 1-4'
107
+ assert_formated_text_for_ast text, [pass(text, 31, 1, 1, 31, 1, 4)]
108
+ end
109
+
110
+ def test_book_with_only_one_chapter_at_begin_of_range
111
+ text = 'Obadja-Jona'
112
+ assert_formated_text_for_ast text, [pass(text, 31, 1, nil, 32, nil, nil)]
113
+ text = 'Obadja 3-Jona 2,4'
114
+ assert_formated_text_for_ast text, [pass(text, 31, 1, 3, 32, 2, 4)]
84
115
  end
85
116
 
86
117
  def test_book_with_only_one_chapter_at_end_of_range
87
- @german = 'Amos 2,4-Obadja 3'
88
- @english = 'Amos 2:4-Obadiah 3'
89
- check_formatting
118
+ text = 'Amos 2,4-Obadja 3'
119
+ assert_formated_text_for_ast text, [pass(text, 30, 2, 4, 31, 1, 3)]
120
+ text = 'Amos 2,4-Obadja 1'
121
+ assert_formated_text_for_ast text, [pass(text, 30, 2, 4, 31, 1, 1)]
90
122
  end
91
123
 
92
- def test_attr_writer_overrides_value_of_mixin
93
- @german = '1. Korinther 1,1 - 2. Korinther 13,13'
94
- @english = '1 Corinthians 1:1 - 2 Corinthians 13:13'
95
- @german_formatter.hyphen_separator = ' - '
96
- @english_formatter.hyphen_separator = ' - '
97
- check_formatting
124
+ ######################################################################
125
+ # more than one passage
126
+ ######################################################################
127
+
128
+ def test_two_books
129
+ text = 'Ruth; Markus'
130
+ t1, t2 = text.split(semi)
131
+ assert_formated_text_for_ast text, [pass(t1, 8, nil, nil, 8, nil, nil), semi, pass(t2, 41, nil, nil, 41, nil, nil)]
98
132
  end
99
133
 
100
- def test_alternative_booknames
101
- ast = @parser.parse('Zephanja 1,8')
102
- assert_equal 'Zefanja 1,8', @german_formatter.format(ast)
134
+ def test_two_complete_refs
135
+ text = 'Ruth 2,1; Markus 4,8'
136
+ t1, t2 = text.split(semi)
137
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 1), semi, pass(t2, 41, 4, 8, 41, 4, 8)]
103
138
  end
104
139
 
105
- def test_addon1
106
- @german = 'Markus 2,4b'
107
- @english = 'Mark 2:4b'
108
- check_formatting
140
+ def test_two_refs_same_book
141
+ text = 'Ruth 2,1; 5,4'
142
+ t1, t2 = text.split(semi)
143
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 1), semi, pass(t2, 8, 5, 4, 8, 5, 4)]
109
144
  end
110
145
 
111
- def test_addon2
112
- @german = 'Markus 2,2-4b'
113
- @english = 'Mark 2:2-4b'
114
- check_formatting
146
+ def test_two_chapters_same_book
147
+ text = 'Ruth 2; 5'
148
+ t1, t2 = text.split(semi)
149
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, nil, 8, 2, nil), semi, pass(t2, 8, 5, nil, 8, 5, nil)]
115
150
  end
116
151
 
117
- def test_both_addons
118
- @german = 'Markus 2,2b-4a'
119
- @english = 'Mark 2:2b-4a'
120
- check_formatting
152
+ def test_two_chapters_different_book
153
+ text = 'Ruth 2; Markus 4'
154
+ t1, t2 = text.split(semi)
155
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, nil, 8, 2, nil), semi, pass(t2, 41, 4, nil, 41, 4, nil)]
121
156
  end
122
157
 
123
- def test_postfix_one_following_verse
124
- @german = 'Markus 2,2f'
125
- @english = 'Mark 2:2f'
126
- check_formatting
158
+ def test_two_verses
159
+ text = 'Ruth 2,5.11'
160
+ t1, t2 = text.split(dot)
161
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 5, 8, 2, 5), dot, pass(t2, 8, 2, 11, 8, 2, 11)]
127
162
  end
128
163
 
129
- def test_postfix_more_following_verses
130
- @german = 'Markus 2,2ff'
131
- @english = 'Mark 2:2ff'
132
- check_formatting
164
+ def test_partial_passage_after_full_passage
165
+ text = 'Ruth 2,5; 4'
166
+ t1, t2 = text.split(semi)
167
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 8, 4, nil, 8, 4, nil)]
168
+ text = 'Ruth 2,5; Markus'
169
+ t1, t2 = text.split(semi)
170
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 41, nil, nil, 41, nil, nil)]
171
+ text = 'Ruth 2,5; Markus 4'
172
+ t1, t2 = text.split(semi)
173
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 41, 4, nil, 41, 4, nil)]
174
+ end
175
+
176
+ ######################################################################
177
+ # mixed variants of more than one passage
178
+ ######################################################################
179
+
180
+ def test_verse_range_and_separated_verse
181
+ text = 'Ruth 2,1-3.11'
182
+ t1, t2 = text.split(dot)
183
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 3), dot, pass(t2, 8, 2, 11, 8, 2, 11)]
184
+ end
185
+
186
+ def test_separate_verse_and_verse_range
187
+ text = 'Ruth 2,1.3-11'
188
+ t1, t2 = text.split(dot)
189
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 1), dot, pass(t2, 8, 2, 3, 8, 2, 11)]
190
+ end
191
+
192
+ def test_two_verse_ranges
193
+ text = 'Ruth 2,1-3.7-11'
194
+ t1, t2 = text.split(dot)
195
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 3), dot, pass(t2, 8, 2, 7, 8, 2, 11)]
196
+ end
197
+
198
+ def test_two_verse_range_different_books
199
+ text = 'Ruth 2,1-11; Markus 4,3-7'
200
+ t1, t2 = text.split(semi)
201
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 11), semi, pass(t2, 41, 4, 3,41, 4, 7)]
202
+ end
203
+
204
+ def test_two_verse_range_different_chapters
205
+ text = 'Ruth 2,1-11; 3,10-19'
206
+ t1, t2 = text.split(semi)
207
+ assert_formated_text_for_ast text, [pass(t1, 8, 2, 1, 8, 2, 11), semi, pass(t2, 8, 3, 10, 8, 3, 19)]
208
+ end
209
+
210
+ def test_book_range_and_following_book
211
+ text = 'Ruth-Markus; Johannes'
212
+ t1, t2 = text.split(semi)
213
+ assert_formated_text_for_ast text, [pass(t1, 8, nil, nil, 41, nil, nil), semi, pass(t2, 43, nil, nil, 43, nil, nil)]
214
+ end
215
+
216
+ def test_chapter_range_and_following_book
217
+ text = 'Ruth 1-2; Johannes 4'
218
+ t1, t2 = text.split(semi)
219
+ assert_formated_text_for_ast text, [pass(t1, 8, 1, nil, 8, 2, nil), semi, pass(t2, 43, 4, nil, 43, 4, nil)]
220
+ end
221
+
222
+ def test_chapter_range_and_following_chapter
223
+ text = 'Ruth 1-2; 4'
224
+ t1, t2 = text.split(semi)
225
+ assert_formated_text_for_ast text, [pass(t1, 8, 1, nil, 8, 2, nil), semi, pass(t2, 8, 4, nil, 8, 4, nil)]
226
+ end
227
+
228
+ def test_book_only_after_full_passage
229
+ text = 'Matthäus 3,4; Markus; Johannes 3,16'
230
+ t1, t2, t3 = text.split(semi)
231
+ assert_formated_text_for_ast text, [pass(t1, 40, 3, 4, 40, 3, 4), semi, pass(t2, 41, nil, nil, 41, nil, nil), semi, pass(t3, 43, 3, 16, 43, 3, 16)]
232
+ end
233
+
234
+ def test_chapter_only_after_full_passage
235
+ text = 'Matthäus 3,4; 8; Johannes 3,16'
236
+ t1, t2, t3 = text.split(semi)
237
+ assert_formated_text_for_ast text, [pass(t1, 40, 3, 4, 40, 3, 4), semi, pass(t2, 40, 8, nil, 40, 8, nil), semi, pass(t3, 43, 3, 16, 43, 3, 16)]
238
+ end
239
+
240
+ ######################################################################
241
+ # complex variants of references
242
+ ######################################################################
243
+
244
+ def test_complex_example
245
+ text = 'Ruth 2,1-11.15; 3,7.9-12; Markus 4; 5,3.18-21'
246
+ t1, t2, t3, t4, t5, t6, t7 = text.split(/; |\./)
247
+ ast = [
248
+ pass(t1, 8, 2, 1, 8, 2, 11), dot,
249
+ pass(t2, 8, 2, 15, 8, 2, 15), semi,
250
+ pass(t3, 8, 3, 7, 8, 3, 7), dot,
251
+ pass(t4, 8, 3, 9, 8, 3, 12), semi,
252
+ pass(t5, 41, 4, nil, 41, 4, nil), semi,
253
+ pass(t6, 41, 5, 3, 41, 5, 3), dot,
254
+ pass(t7, 41, 5, 18, 41, 5, 21)
255
+ ]
256
+ assert_formated_text_for_ast text, ast
133
257
  end
134
258
 
135
259
  private
136
260
 
137
- def check_formatting
138
- ast = @parser.parse(@german)
139
- assert_equal @german, @german_formatter.format(ast)
140
- assert_equal @english, @english_formatter.format(ast)
261
+ def assert_formated_text_for_ast text, ast
262
+ assert_equal text, @german_formatter.format(ast)
141
263
  end
142
264
 
143
265
  end
@@ -0,0 +1,143 @@
1
+ # - encoding: utf-8 -
2
+ require 'test/unit'
3
+ require 'test_helper'
4
+ require 'scripref'
5
+ require 'scripref/english'
6
+ require 'scripref/formatter'
7
+ require 'scripref/german'
8
+ require 'scripref/parser'
9
+
10
+ class TestIntegration < Test::Unit::TestCase
11
+
12
+ include Test::Helper
13
+
14
+ def setup
15
+ @parser = Scripref::Parser.new(Scripref::German)
16
+ @german_formatter = Scripref::Formatter.new(Scripref::German)
17
+ @english_formatter = Scripref::Formatter.new(Scripref::English)
18
+ end
19
+
20
+ def test_only_book
21
+ @german = 'Römer'
22
+ @english = 'Romans'
23
+ check_formatting
24
+ end
25
+
26
+ def test_book_and_chapter
27
+ @german = 'Römer 8'
28
+ @english = 'Romans 8'
29
+ check_formatting
30
+ end
31
+
32
+ def test_one_verse
33
+ @german = 'Römer 6,23'
34
+ @english = 'Romans 6:23'
35
+ check_formatting
36
+ end
37
+
38
+ def test_book_range
39
+ @german = 'Römer-Hebräer'
40
+ @english = 'Romans-Hebrews'
41
+ check_formatting
42
+ end
43
+
44
+ def test_chapter_range
45
+ @german = 'Römer 1-8'
46
+ @english = 'Romans 1-8'
47
+ check_formatting
48
+ end
49
+
50
+ def test_simple_passage
51
+ @german = 'Römer 8,1-10'
52
+ @english = 'Romans 8:1-10'
53
+ check_formatting
54
+ end
55
+
56
+ def test_passage_with_chapter_change
57
+ @german = 'Römer 1,1-5,11'
58
+ @english = 'Romans 1:1-5:11'
59
+ check_formatting
60
+ end
61
+
62
+ def test_passage_with_book_change
63
+ @german = '1. Korinther 1,1-2. Korinther 13,13'
64
+ @english = '1 Corinthians 1:1-2 Corinthians 13:13'
65
+ check_formatting
66
+ end
67
+
68
+ def test_passage_with_different_chapter_and_same_verse
69
+ @german = '2. Petrus 1,13-2,13'
70
+ @english = '2 Peter 1:13-2:13'
71
+ check_formatting
72
+ end
73
+
74
+ def test_book_with_only_one_chapter
75
+ @german = 'Obadja 3'
76
+ @english = 'Obadiah 3'
77
+ check_formatting
78
+ end
79
+
80
+ def test_book_with_only_one_chapter_range
81
+ @german = 'Obadja 3-5'
82
+ @english = 'Obadiah 3-5'
83
+ check_formatting
84
+ end
85
+
86
+ def test_book_with_only_one_chapter_at_end_of_range
87
+ @german = 'Amos 2,4-Obadja 3'
88
+ @english = 'Amos 2:4-Obadiah 3'
89
+ check_formatting
90
+ end
91
+
92
+ def test_attr_writer_overrides_value_of_mixin
93
+ @german = '1. Korinther 1,1 - 2. Korinther 13,13'
94
+ @english = '1 Corinthians 1:1 - 2 Corinthians 13:13'
95
+ @german_formatter.hyphen_separator = ' - '
96
+ @english_formatter.hyphen_separator = ' - '
97
+ check_formatting
98
+ end
99
+
100
+ def test_alternative_booknames
101
+ ast = @parser.parse('Zephanja 1,8')
102
+ assert_equal 'Zefanja 1,8', @german_formatter.format(ast)
103
+ end
104
+
105
+ def test_addon1
106
+ @german = 'Markus 2,4b'
107
+ @english = 'Mark 2:4b'
108
+ check_formatting
109
+ end
110
+
111
+ def test_addon2
112
+ @german = 'Markus 2,2-4b'
113
+ @english = 'Mark 2:2-4b'
114
+ check_formatting
115
+ end
116
+
117
+ def test_both_addons
118
+ @german = 'Markus 2,2b-4a'
119
+ @english = 'Mark 2:2b-4a'
120
+ check_formatting
121
+ end
122
+
123
+ def test_postfix_one_following_verse
124
+ @german = 'Markus 2,2f'
125
+ @english = 'Mark 2:2f'
126
+ check_formatting
127
+ end
128
+
129
+ def test_postfix_more_following_verses
130
+ @german = 'Markus 2,2ff'
131
+ @english = 'Mark 2:2ff'
132
+ check_formatting
133
+ end
134
+
135
+ private
136
+
137
+ def check_formatting
138
+ ast = @parser.parse(@german)
139
+ assert_equal @german, @german_formatter.format(ast)
140
+ assert_equal @english, @english_formatter.format(ast)
141
+ end
142
+
143
+ end
@@ -116,6 +116,15 @@ class TestParser < Test::Unit::TestCase
116
116
  assert_parsed_ast_for_text [pass(text, 31, 1, 1, 31, 1, 4)], text
117
117
  end
118
118
 
119
+ def test_book_with_only_one_chapter_at_begin_of_range
120
+ text = 'Obad - Jona'
121
+ assert_parsed_ast_for_text [pass(text, 31, 1, nil, 32, nil, nil)], text
122
+ text = 'Obad 3 - Jona 2,4'
123
+ assert_parsed_ast_for_text [pass(text, 31, 1, 3, 32, 2, 4)], text
124
+ text = 'Obad 1,3 - Jona 2,4'
125
+ assert_parsed_ast_for_text [pass(text, 31, 1, 3, 32, 2, 4)], text
126
+ end
127
+
119
128
  def test_book_with_only_one_chapter_at_end_of_range
120
129
  text = 'Amos 2,4 - Obad 3'
121
130
  assert_parsed_ast_for_text [pass(text, 30, 2, 4, 31, 1, 3)], text
@@ -128,9 +137,15 @@ class TestParser < Test::Unit::TestCase
128
137
  end
129
138
 
130
139
  ######################################################################
131
- # more than one reference
140
+ # more than one passage
132
141
  ######################################################################
133
142
 
143
+ def test_two_books
144
+ text = 'Ruth; Markus'
145
+ t1, t2 = text.split(semi)
146
+ assert_parsed_ast_for_text [pass(t1, 8, nil, nil, 8, nil, nil), semi, pass(t2, 41, nil, nil, 41, nil, nil)], text
147
+ end
148
+
134
149
  def test_two_complete_refs
135
150
  text = 'Ruth 2,1; Markus 4,8'
136
151
  t1, t2 = text.split(semi)
@@ -161,8 +176,20 @@ class TestParser < Test::Unit::TestCase
161
176
  assert_parsed_ast_for_text [pass(t1, 8, 2, 5, 8, 2, 5), dot, pass(t2, 8, 2, 11, 8, 2, 11)], text
162
177
  end
163
178
 
179
+ def test_partial_passage_after_full_passage
180
+ text = 'Ruth 2,5; 4'
181
+ t1, t2 = text.split(semi)
182
+ assert_parsed_ast_for_text [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 8, 4, nil, 8, 4, nil)], text
183
+ text = 'Ruth 2,5; Markus'
184
+ t1, t2 = text.split(semi)
185
+ assert_parsed_ast_for_text [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 41, nil, nil, 41, nil, nil)], text
186
+ text = 'Ruth 2,5; Markus 4'
187
+ t1, t2 = text.split(semi)
188
+ assert_parsed_ast_for_text [pass(t1, 8, 2, 5, 8, 2, 5), semi, pass(t2, 41, 4, nil, 41, 4, nil)], text
189
+ end
190
+
164
191
  ######################################################################
165
- # mixed variants of more than one reference
192
+ # mixed variants of more than one passage
166
193
  ######################################################################
167
194
 
168
195
  def test_verse_range_and_separated_verse
@@ -195,6 +222,36 @@ class TestParser < Test::Unit::TestCase
195
222
  assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 11), semi, pass(t2, 8, 3, 10, 8, 3, 19)], text
196
223
  end
197
224
 
225
+ def test_book_range_and_following_book
226
+ text = 'Ruth-Markus; Johannes'
227
+ t1, t2 = text.split(semi)
228
+ assert_parsed_ast_for_text [pass(t1, 8, nil, nil, 41, nil, nil), semi, pass(t2, 43, nil, nil, 43, nil, nil)], text
229
+ end
230
+
231
+ def test_chapter_range_and_following_book
232
+ text = 'Ruth 1-2; Joh 4'
233
+ t1, t2 = text.split(semi)
234
+ assert_parsed_ast_for_text [pass(t1, 8, 1, nil, 8, 2, nil), semi, pass(t2, 43, 4, nil, 43, 4, nil)], text
235
+ end
236
+
237
+ def test_chapter_range_and_following_chapter
238
+ text = 'Ruth 1-2; 4'
239
+ t1, t2 = text.split(semi)
240
+ assert_parsed_ast_for_text [pass(t1, 8, 1, nil, 8, 2, nil), semi, pass(t2, 8, 4, nil, 8, 4, nil)], text
241
+ end
242
+
243
+ def test_book_only_after_full_passage
244
+ text = 'Matt 3,4; Mar; Joh 3,16'
245
+ t1, t2, t3 = text.split(semi)
246
+ assert_parsed_ast_for_text [pass(t1, 40, 3, 4, 40, 3, 4), semi, pass(t2, 41, nil, nil, 41, nil, nil), semi, pass(t3, 43, 3, 16, 43, 3, 16)], text
247
+ end
248
+
249
+ def test_chapter_only_after_full_passage
250
+ text = 'Matt 3,4; 8; Joh 3,16'
251
+ t1, t2, t3 = text.split(semi)
252
+ assert_parsed_ast_for_text [pass(t1, 40, 3, 4, 40, 3, 4), semi, pass(t2, 40, 8, nil, 40, 8, nil), semi, pass(t3, 43, 3, 16, 43, 3, 16)], text
253
+ end
254
+
198
255
  ######################################################################
199
256
  # complex variants of references
200
257
  ######################################################################
@@ -14,10 +14,75 @@ class TestPassage < Test::Unit::TestCase
14
14
  assert_equal [41, 1, 2, 42, 3, 4], pass.to_a
15
15
  end
16
16
 
17
- def test_ordering
17
+ def test_spaceship_operator
18
+ ast = @parser.parse('Mar 2,3; Joh 1,5')
19
+ p1, p2 = ast[0], ast[2]
20
+ assert_nil p1 <=> :other_value
21
+ assert_nil :other_value <=> p1
22
+ assert_equal (-1), p1 <=> p2
23
+ assert_equal 0, p1 <=> p1
24
+ assert_equal 1, p2 <=> p1
25
+ end
26
+
27
+ def test_comparable_with_sort
18
28
  ast = @parser.parse('Joh 8,1-9,11; 8,2-9,12; 8,2-9,11; 8,1-9,12; Joh 8')
19
- passages = ast.select {|e| Scripref::Passage === e}
20
- assert_equal ["Joh 8", "Joh 8,1-9,11", "8,1-9,12", "8,2-9,11", "8,2-9,12"], passages.sort.map(&:text)
29
+ passages = ast.grep(Scripref::Passage)
30
+ expect = ['Joh 8',
31
+ 'Joh 8,1-9,11',
32
+ '8,1-9,12',
33
+ '8,2-9,11',
34
+ '8,2-9,12']
35
+ assert_equal expect, passages.sort.map(&:text)
36
+
37
+ ast = @parser.parse('Mar 1; 1,1; 1,1f; 1,1ff; 1,2; 1,1-2,2; Mar 1-2; Markus; Markus-Lukas; Mar 1-Luk 2; Mar 1,1-Luk 2,2')
38
+ passages = ast.grep(Scripref::Passage)
39
+ formatter = Scripref::Formatter.new(Scripref::German)
40
+ expect = ['Markus 1,1',
41
+ 'Markus 1,1f',
42
+ 'Markus 1,1ff',
43
+ 'Markus 1',
44
+ 'Markus 1,1-2,2',
45
+ 'Markus 1-2',
46
+ 'Markus',
47
+ 'Markus 1,1-Lukas 2,2',
48
+ 'Markus 1-Lukas 2',
49
+ 'Markus-Lukas',
50
+ 'Markus 1,2']
51
+ assert_equal expect, passages.sort.map {|e| formatter << e}
52
+ end
53
+
54
+ def test_overlap
55
+ a = @parser.parse('Joh 8,1-9').first
56
+ b = @parser.parse('Joh 8,8-11').first
57
+ c = @parser.parse('Joh 8,12-15').first
58
+ d = @parser.parse('Joh 8,15-18').first
59
+ e = @parser.parse('Joh 8').first
60
+ assert_overlap a, a
61
+ assert_overlap a, b
62
+ assert_not_overlap b, c
63
+ assert_overlap c, d
64
+ assert_overlap d, e
65
+ end
66
+
67
+ def test_start
68
+ p = Scripref::Passage.new('', 1, 2, 3, 4, 5, 6)
69
+ assert_equal [1, 2, 3], p.start
21
70
  end
22
71
 
72
+ def test_end
73
+ p = Scripref::Passage.new('', 1, 2, 3, 4, 5, 6)
74
+ assert_equal [4, 5, 6], p.end
75
+ end
76
+
77
+ protected
78
+
79
+ def assert_overlap a, b
80
+ assert a.overlap?(b)
81
+ assert b.overlap?(a)
82
+ end
83
+
84
+ def assert_not_overlap a, b
85
+ assert !a.overlap?(b)
86
+ assert !b.overlap?(a)
87
+ end
23
88
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scripref
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Friedrich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-19 00:00:00.000000000 Z
11
+ date: 2016-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rim
@@ -44,7 +44,7 @@ executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
- - CHANGELOG
47
+ - Changelog
48
48
  - LICENSE
49
49
  - README.md
50
50
  - Rakefile
@@ -54,6 +54,7 @@ files:
54
54
  - lib/scripref/formatter.rb
55
55
  - lib/scripref/german.rb
56
56
  - lib/scripref/parser.rb
57
+ - lib/scripref/passage.rb
57
58
  - lib/scripref/pipelining.rb
58
59
  - lib/scripref/processor.rb
59
60
  - regtest/formatter.rb
@@ -64,6 +65,7 @@ files:
64
65
  - test/test_formatter.rb
65
66
  - test/test_german.rb
66
67
  - test/test_helper.rb
68
+ - test/test_integration.rb
67
69
  - test/test_parser.rb
68
70
  - test/test_passage.rb
69
71
  - test/test_pipelining.rb
@@ -87,9 +89,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
89
  version: '0'
88
90
  requirements: []
89
91
  rubyforge_project:
90
- rubygems_version: 2.5.1
92
+ rubygems_version: 2.6.3
91
93
  signing_key:
92
94
  specification_version: 4
93
95
  summary: Library for parsing scripture references in real texts.
94
96
  test_files: []
95
- has_rdoc: