scripref 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +8 -0
- data/lib/scripref/const_reader.rb +8 -1
- data/lib/scripref/english.rb +10 -0
- data/lib/scripref/formatter.rb +39 -28
- data/lib/scripref/german.rb +13 -0
- data/lib/scripref/parser.rb +37 -19
- data/lib/scripref/processor.rb +1 -3
- data/lib/scripref.rb +1 -6
- data/test/test_formatter.rb +19 -1
- data/test/test_german.rb +1 -0
- data/test/test_parser.rb +24 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 373b4b572bcb6fadc58872590bc98e75f5bebe3c
|
4
|
+
data.tar.gz: be215c400b76c7327bdeb63b1bff52917c854eca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc24a4742a42477c252edd1c06fb52f2b41bb6411479556921b39e2512082accc7ce9270d0d87dc6b86032ba13847f3bf9074268b18ac0cce789cd90faf8918c
|
7
|
+
data.tar.gz: 31e56ca2e1000abc2a8bdcdf6b7af0c99b6c49e604dbdd0f530dd02416b4e1d188884ff4428e466c3b367439357876c4b66d4244ca61e42e6bfb4a59de283608
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.8.0
|
2
|
+
Formatting of verse addons implemented.
|
3
|
+
Refactoring: Rename methods in Formatter to distinguish between format_* and process_*.
|
4
|
+
Refactoring: Move method Scripref.book_has_only_one_chapter to mixins.
|
5
|
+
New methods Parser#chapter_re and #verse_re.
|
6
|
+
New method Parser#special_abbrev_mapping to allow to parse special abbreviations, for example "Phil" to "Philipper" in German.
|
7
|
+
Some bugs fixed.
|
8
|
+
|
1
9
|
0.7.1
|
2
10
|
Add Psalmen as alternative German book name.
|
3
11
|
Add E-Mail address.
|
@@ -37,7 +37,14 @@ module ConstReader
|
|
37
37
|
consts.flatten.each do |c|
|
38
38
|
class_exec(c.to_s, c.to_s.downcase) do |c_name, m_name|
|
39
39
|
define_method m_name do
|
40
|
-
|
40
|
+
ivar = '@' << m_name
|
41
|
+
if instance_variable_defined? ivar
|
42
|
+
return instance_variable_get(ivar)
|
43
|
+
else
|
44
|
+
val = self.singleton_class.const_get c_name
|
45
|
+
instance_variable_set ivar, val
|
46
|
+
return val
|
47
|
+
end
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
data/lib/scripref/english.rb
CHANGED
@@ -50,6 +50,16 @@ module Scripref
|
|
50
50
|
# Regular expression to parse a reference
|
51
51
|
REFERENCE_RE = /#{pass}(;\s*#{pass})*/o
|
52
52
|
|
53
|
+
# Check if book has only one chapter
|
54
|
+
# @param book book as number
|
55
|
+
def book_has_only_one_chapter? book
|
56
|
+
[31, 63, 64, 65].include?(book)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generate attr_reader methods for all constants
|
60
|
+
extend ConstReader
|
61
|
+
const_reader constants
|
62
|
+
|
53
63
|
end
|
54
64
|
|
55
65
|
end
|
data/lib/scripref/formatter.rb
CHANGED
@@ -4,16 +4,13 @@ module Scripref
|
|
4
4
|
|
5
5
|
class Formatter
|
6
6
|
|
7
|
+
attr_accessor :cv_separator, :hyphen_separator, :pass_separator
|
8
|
+
|
9
|
+
|
7
10
|
# @param mods one or more modules to include
|
8
11
|
def initialize *mods
|
9
12
|
@mods = mods
|
10
|
-
mods.each
|
11
|
-
m.class_eval do
|
12
|
-
extend ConstReader
|
13
|
-
const_accessor constants
|
14
|
-
end
|
15
|
-
extend m
|
16
|
-
end
|
13
|
+
mods.each {|m| extend m}
|
17
14
|
end
|
18
15
|
|
19
16
|
# Formats a reference (array of passages)
|
@@ -22,56 +19,64 @@ module Scripref
|
|
22
19
|
@result = ''
|
23
20
|
reference.flatten.each do |pass|
|
24
21
|
@pass = pass
|
25
|
-
|
22
|
+
process_passage
|
26
23
|
end
|
27
24
|
@result
|
28
25
|
end
|
29
26
|
|
30
|
-
def format_passage
|
31
|
-
@changed = false
|
32
|
-
format_b1
|
33
|
-
end
|
34
|
-
|
35
27
|
def format_book num
|
36
28
|
Array(book_names[num - 1]).first
|
37
29
|
end
|
38
30
|
|
39
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def process_passage
|
34
|
+
@changed = false
|
35
|
+
process_b1
|
36
|
+
end
|
37
|
+
|
38
|
+
def process_b1
|
40
39
|
b1 = @pass.b1
|
41
40
|
if @last_b != b1
|
42
41
|
@result << format_book(b1)
|
43
42
|
@last_b = b1
|
44
43
|
@changed = true
|
45
44
|
end
|
46
|
-
|
45
|
+
process_c1
|
47
46
|
end
|
48
47
|
|
49
|
-
def
|
48
|
+
def process_c1
|
50
49
|
c1 = @pass.c1
|
51
50
|
if c1 && (@changed || @last_c != c1)
|
52
51
|
@result << ' '
|
53
|
-
if !
|
52
|
+
if ! book_has_only_one_chapter?(@pass.b1)
|
54
53
|
@result << c1.to_s
|
55
54
|
end
|
56
55
|
@last_c = c1
|
57
56
|
@changed = true
|
58
57
|
end
|
59
|
-
|
58
|
+
process_v1
|
60
59
|
end
|
61
60
|
|
62
|
-
def
|
61
|
+
def process_v1
|
63
62
|
v1 = @pass.v1
|
64
63
|
if v1 && (@changed || @last_v != v1)
|
65
|
-
if !
|
64
|
+
if ! book_has_only_one_chapter?(@pass.b1)
|
66
65
|
@result << cv_separator
|
67
66
|
end
|
68
67
|
@result << v1.to_s
|
69
68
|
@last_v = v1
|
69
|
+
process_a1
|
70
70
|
end
|
71
|
-
|
71
|
+
process_b2
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
74
|
+
def process_a1
|
75
|
+
a1 = @pass.a1
|
76
|
+
@result << a1.to_s if a1
|
77
|
+
end
|
78
|
+
|
79
|
+
def process_b2
|
75
80
|
@changed = false
|
76
81
|
@hyphen = false
|
77
82
|
b2 = @pass.b2
|
@@ -82,10 +87,10 @@ module Scripref
|
|
82
87
|
@changed = true
|
83
88
|
@hyphen = true
|
84
89
|
end
|
85
|
-
|
90
|
+
process_c2
|
86
91
|
end
|
87
92
|
|
88
|
-
def
|
93
|
+
def process_c2
|
89
94
|
c2 = @pass.c2
|
90
95
|
if c2 && (@changed || @last_c != c2)
|
91
96
|
if @hyphen
|
@@ -94,20 +99,20 @@ module Scripref
|
|
94
99
|
@result << hyphen_separator
|
95
100
|
@hyphen = true
|
96
101
|
end
|
97
|
-
if !
|
102
|
+
if ! book_has_only_one_chapter?(@pass.b2)
|
98
103
|
@result << c2.to_s
|
99
104
|
end
|
100
105
|
@last_c = c2
|
101
106
|
@changed = true
|
102
107
|
end
|
103
|
-
|
108
|
+
process_v2
|
104
109
|
end
|
105
110
|
|
106
|
-
def
|
111
|
+
def process_v2
|
107
112
|
v2 = @pass.v2
|
108
113
|
if v2 && (@changed || @last_v != v2)
|
109
114
|
if @hyphen
|
110
|
-
if !
|
115
|
+
if ! book_has_only_one_chapter?(@pass.b2)
|
111
116
|
@result << cv_separator
|
112
117
|
end
|
113
118
|
else
|
@@ -117,9 +122,15 @@ module Scripref
|
|
117
122
|
@result << v2.to_s
|
118
123
|
@last_v = @v2
|
119
124
|
@changed = true
|
125
|
+
process_a2
|
120
126
|
end
|
121
127
|
end
|
122
128
|
|
129
|
+
def process_a2
|
130
|
+
a2 = @pass.a2
|
131
|
+
@result << a2.to_s if a2
|
132
|
+
end
|
133
|
+
|
123
134
|
alias << format
|
124
135
|
|
125
136
|
end
|
data/lib/scripref/german.rb
CHANGED
@@ -47,6 +47,19 @@ module Scripref
|
|
47
47
|
# Regular expression to parse a reference
|
48
48
|
REFERENCE_RE = /#{pass}(;\s*#{pass})*/o
|
49
49
|
|
50
|
+
# Check if book has only one chapter
|
51
|
+
# @param book book as number
|
52
|
+
def book_has_only_one_chapter? book
|
53
|
+
[31, 63, 64, 65].include?(book)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Hash with special abbreviations
|
57
|
+
SPECIAL_ABBREV_MAPPING = {'Phil' => 'Philipper'}
|
58
|
+
|
59
|
+
# Generate attr_reader methods for all constants
|
60
|
+
extend ConstReader
|
61
|
+
const_reader constants
|
62
|
+
|
50
63
|
end
|
51
64
|
|
52
65
|
end
|
data/lib/scripref/parser.rb
CHANGED
@@ -7,18 +7,29 @@ module Scripref
|
|
7
7
|
|
8
8
|
attr_reader :error
|
9
9
|
|
10
|
-
NUMBER_RE = /\d+\s*/
|
10
|
+
NUMBER_RE = /\d+\s*/o
|
11
11
|
|
12
12
|
# @param mods one or more modules to include
|
13
13
|
def initialize *mods
|
14
14
|
@mods = mods
|
15
|
-
mods.each
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
mods.each {|m| extend m}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Regular expression to match a chapter
|
19
|
+
def chapter_re
|
20
|
+
NUMBER_RE
|
21
|
+
end
|
22
|
+
|
23
|
+
# Regular expression to match a verse
|
24
|
+
def verse_re
|
25
|
+
NUMBER_RE
|
26
|
+
end
|
27
|
+
|
28
|
+
# Hash with special abbreviations
|
29
|
+
# for example {'Phil' => 'Philipper'}
|
30
|
+
# usual overwritten in Mixins
|
31
|
+
def special_abbrev_mapping
|
32
|
+
Hash.new
|
22
33
|
end
|
23
34
|
|
24
35
|
# Parsing a string of a scripture reference
|
@@ -42,12 +53,12 @@ module Scripref
|
|
42
53
|
@text << s
|
43
54
|
@b1 = @b2 = abbrev2num(s)
|
44
55
|
|
45
|
-
if check(Regexp.new(
|
56
|
+
if check(Regexp.new(chapter_re.source + cv_sep_re.source))
|
46
57
|
@c1 = @v1 = nil
|
47
58
|
@c2 = @v2 = nil
|
48
59
|
c1
|
49
60
|
else
|
50
|
-
if
|
61
|
+
if book_has_only_one_chapter?(@b1)
|
51
62
|
@c1 = @c2 = 1
|
52
63
|
epsilon or (hyphen and b2) or v1 or give_up 'EOS or hyphen and book or verse expected!'
|
53
64
|
else
|
@@ -60,7 +71,7 @@ module Scripref
|
|
60
71
|
|
61
72
|
# try parse first chapter
|
62
73
|
def c1
|
63
|
-
s = scan(
|
74
|
+
s = scan(chapter_re) or return nil
|
64
75
|
@text << s
|
65
76
|
@c1 = @c2 = s.to_i
|
66
77
|
|
@@ -77,7 +88,7 @@ module Scripref
|
|
77
88
|
|
78
89
|
# try to parse first verse
|
79
90
|
def v1
|
80
|
-
s = scan(
|
91
|
+
s = scan(verse_re) or return nil
|
81
92
|
@text << s
|
82
93
|
@v1 = @v2 = s.to_i
|
83
94
|
|
@@ -92,7 +103,7 @@ module Scripref
|
|
92
103
|
|
93
104
|
if hyphen
|
94
105
|
b2 or (
|
95
|
-
if check(Regexp.new(
|
106
|
+
if check(Regexp.new(chapter_re.source + cv_sep_re.source))
|
96
107
|
c2
|
97
108
|
else
|
98
109
|
v2 or give_up 'Chapter or verse expected!'
|
@@ -113,10 +124,10 @@ module Scripref
|
|
113
124
|
@b2 = abbrev2num(s)
|
114
125
|
@c2 = @v2 = nil
|
115
126
|
|
116
|
-
if check(Regexp.new(
|
127
|
+
if check(Regexp.new(chapter_re.source + cv_sep_re.source))
|
117
128
|
c2
|
118
129
|
else
|
119
|
-
if
|
130
|
+
if book_has_only_one_chapter?(@b2)
|
120
131
|
@c2 = 1
|
121
132
|
epsilon or v2 or give_up 'EOS or chapter or verse expected!'
|
122
133
|
else
|
@@ -127,7 +138,7 @@ module Scripref
|
|
127
138
|
|
128
139
|
# try to parse second chapter
|
129
140
|
def c2
|
130
|
-
s = scan(
|
141
|
+
s = scan(chapter_re) or return nil
|
131
142
|
@text << s
|
132
143
|
@c2 = s.to_i
|
133
144
|
|
@@ -140,7 +151,7 @@ module Scripref
|
|
140
151
|
|
141
152
|
# try to parse second verse
|
142
153
|
def v2
|
143
|
-
s = scan(
|
154
|
+
s = scan(verse_re) or return nil
|
144
155
|
@text << s
|
145
156
|
@v2 = s.to_i
|
146
157
|
|
@@ -241,11 +252,18 @@ module Scripref
|
|
241
252
|
end
|
242
253
|
|
243
254
|
def abbrev2book str
|
255
|
+
s = str.strip
|
256
|
+
if name = special_abbrev_mapping[s]
|
257
|
+
return name
|
258
|
+
end
|
244
259
|
@books_str ||= ('#' << book_names.flatten.join('#') << '#')
|
245
|
-
pattern =
|
260
|
+
pattern = s.chars.map {|c| Regexp.escape(c) << '[^#]*'}.join
|
246
261
|
re = /(?<=#)#{pattern}(?=#)/
|
247
262
|
names = @books_str.scan(re)
|
248
|
-
|
263
|
+
if names.size != 1
|
264
|
+
unscan
|
265
|
+
give_up format("Abbreviation %s is ambiguous it matches %s!", s, names.join(', '))
|
266
|
+
end
|
249
267
|
names.first
|
250
268
|
end
|
251
269
|
|
data/lib/scripref/processor.rb
CHANGED
data/lib/scripref.rb
CHANGED
@@ -8,7 +8,7 @@ require 'scripref/german'
|
|
8
8
|
|
9
9
|
module Scripref
|
10
10
|
|
11
|
-
VERSION = '0.
|
11
|
+
VERSION = '0.8.0'
|
12
12
|
|
13
13
|
Passage = Struct.new(:text, :b1, :c1, :v1, :b2, :c2, :v2, :a1, :a2) do
|
14
14
|
|
@@ -39,9 +39,4 @@ module Scripref
|
|
39
39
|
class PassSep < Sep; end
|
40
40
|
class VerseSep < Sep; end
|
41
41
|
|
42
|
-
# check if the book has only one chapter
|
43
|
-
def self.book_has_only_one_chapter? book
|
44
|
-
[31, 63, 64, 65].include?(book)
|
45
|
-
end
|
46
|
-
|
47
42
|
end
|
data/test/test_formatter.rb
CHANGED
@@ -89,7 +89,7 @@ class TestFormatter < Test::Unit::TestCase
|
|
89
89
|
check_formatting
|
90
90
|
end
|
91
91
|
|
92
|
-
def
|
92
|
+
def test_attr_writer_overrides_value_of_mixin
|
93
93
|
@german = '1. Korinther 1,1 - 2. Korinther 13,13'
|
94
94
|
@english = '1 Corinthians 1:1 - 2 Corinthians 13:13'
|
95
95
|
@german_formatter.hyphen_separator = ' - '
|
@@ -102,6 +102,24 @@ class TestFormatter < Test::Unit::TestCase
|
|
102
102
|
assert_equal 'Zefanja 1,8', @german_formatter.format(ast)
|
103
103
|
end
|
104
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
|
+
|
105
123
|
private
|
106
124
|
|
107
125
|
def check_formatting
|
data/test/test_german.rb
CHANGED
data/test/test_parser.rb
CHANGED
@@ -229,4 +229,28 @@ class TestParser < Test::Unit::TestCase
|
|
229
229
|
assert_equal formated_error, @parser.format_error
|
230
230
|
end
|
231
231
|
|
232
|
+
def test_error_message_for_unambiguous_book
|
233
|
+
text = 'Ruth 2,4; M 3,8'
|
234
|
+
begin
|
235
|
+
@parser.parse text
|
236
|
+
rescue Scripref::ParserError
|
237
|
+
end
|
238
|
+
assert_match /^Abbreviation M is ambiguous/, @parser.error
|
239
|
+
formated_error = "Abbreviation M is ambiguous it matches Micha, Maleachi, Matthäus, Markus!\nRuth 2,4; M 3,8\n ^"
|
240
|
+
assert_equal formated_error, @parser.format_error
|
241
|
+
end
|
242
|
+
|
243
|
+
######################################################################
|
244
|
+
# special things
|
245
|
+
######################################################################
|
246
|
+
|
247
|
+
def test_special_book_abbrev
|
248
|
+
# Abbrev "Phil" would technical match "Philipper" and "Philemon"
|
249
|
+
# and therefore throw a ParserError because it's ambiguous,
|
250
|
+
# but in German the abbrev "Phil" is generally used for "Philipper",
|
251
|
+
# so the parser should be able to support such behaviour.
|
252
|
+
text = 'Phil 4,4'
|
253
|
+
assert_parsed_ast_for_text [pass(text, 50, 4, 4, 50, 4, 4)], text
|
254
|
+
end
|
255
|
+
|
232
256
|
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.
|
4
|
+
version: 0.8.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-
|
11
|
+
date: 2016-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rim
|