scripref 1.2.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 740c7e151f3f9e268593a919349a63563ae6c5abc53ebd1819ff210062e36bbc
4
- data.tar.gz: 49b5d3b12e95c7aa7df8c556f0e370f5af82b22fe8e6421d9dead148eab31881
3
+ metadata.gz: 41762855bac59cfd4181dacab1ae3cb5d5fa879e08e841d60d9fbde5170a5f65
4
+ data.tar.gz: debe69c84f21f2d0af4e5ba88ddd8a0ee89c78ca449a4dc0ee302c593ecb46a0
5
5
  SHA512:
6
- metadata.gz: 17a6871933eb137c90b2187afb21cbb0398aeeab896ae080a9efb1b433876b70e6406a4d27355ed61e4710de76fd736876d42fdc613ffe0860acebdfabcda888
7
- data.tar.gz: 5d4e55dc849c3f3935d32b387deaf559090cd478fc034586f3005b4aa5dfe4f1d8e8bf2d63016936692a4974785f00afc403ebf04aa58b5eb52b9cef09a040de
6
+ metadata.gz: 40877991379c9c1d743fa68575fdc2de3d8f16984483e0b121aa306913f18f5c06af30cc0fee604ea8c2d9678989811388a8c2e12980a74ee7a390051da56345
7
+ data.tar.gz: b80cdba6be11573f7691913d8415a0c45874996e6050ef4f6fd91535006ffcffb2cdaa4e714b5ede4649b617abfb6a795c73b3b2d655420786fe78c574eec2f5
data/Changelog CHANGED
@@ -1,3 +1,13 @@
1
+ 2.0.0
2
+ Major release with following breaking changes:
3
+ Rewrite Bookorder and Bookname and adapt Formatter#format accordingly.
4
+ Remove Comparable mixin and depending methods from Passage and implement
5
+ Sorter instead.
6
+ Rename all osis_*_id names to book_id.
7
+ Rename OSIS_BOOK_ID_TO_BOOK_NAME -> BOOKNAMES_HASH
8
+
9
+ Further: Implement a lot of internal optimizations.
10
+
1
11
  1.2.2
2
12
  Extend German abbreviations.
3
13
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2018, 2020, 2024 Jan Friedrich
1
+ Copyright (c) 2010-2018, 2020, 2024-2026 Jan Friedrich
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -18,17 +18,23 @@ module Scripref
18
18
  NUMBER_RE
19
19
  end
20
20
 
21
- # Regular expression to match a book.
21
+ # Regular expression to match a book
22
22
  def book_re
23
23
  return @book_re if @book_re
24
- books_res_as_strings = book_names.map do |bn|
25
- bn.names.map do |n|
26
- (n.gsub(/([^\dA-Z])/, '\1?').gsub('.', '\.'))
24
+ books_res_as_strings = []
25
+ each_bookname do |bn|
26
+ bn.each_name do |n|
27
+ books_res_as_strings << (n.gsub(/([^\dA-Z])/, '\1?').gsub('.', '\.'))
27
28
  end
28
- end.flatten
29
+ end
29
30
  @book_re = Regexp.compile(books_res_as_strings.map {|s| '(\b' << s << '\b\.?\s*)' }.join('|'), nil)
30
31
  end
31
32
 
33
+ # Enumerator over booknames
34
+ def each_bookname &blk
35
+ booknames_hash.each_value(&blk)
36
+ end
37
+
32
38
  end
33
39
 
34
40
  end
@@ -5,28 +5,106 @@ module Scripref
5
5
 
6
6
  class Bookname
7
7
 
8
- attr_reader :osis_id, :names, :abbrevs
8
+ attr_reader :book_id
9
9
 
10
- def initialize osis_id:, names:, abbrevs:
11
- @osis_id = osis_id
12
- @names = Array(names)
10
+ # @param book_id OSID-ID of the book
11
+ # @param name full name of the book
12
+ # @param abbrevs possible abbreviations for the book
13
+ # @param alternatives further Bookname instances with alternative names and abbreviations for book
14
+ def initialize book_id:, name:, abbrevs: [], alternatives: []
15
+ @book_id = book_id
16
+ @name = name
13
17
  @abbrevs = Array(abbrevs)
18
+ @alternatives = Array(alternatives)
14
19
  end
15
20
 
16
- def name
17
- @names.first
21
+ # Format the bookname (full name or abbreviation)
22
+ # @param abbrev_level if 0 full name, if >0 an abbreviation
23
+ def format abbrev_level: 0
24
+ case
25
+ when abbrev_level == 0
26
+ @name
27
+ when abbrev_level > 0
28
+ @abbrevs[abbrev_level - 1] || @abbrevs[-1] || @name
29
+ else
30
+ fail ArgumentError, 'negative values for abbrev_level are not allowed'
31
+ end
18
32
  end
19
33
 
20
- def abbrev level=0
21
- @abbrevs[level] || @abbrevs[-1]
34
+ # Enumerator over all names (name and name of alternatives)
35
+ def each_name
36
+ if block_given?
37
+ yield @name
38
+ @alternatives.each do |bn|
39
+ bn.each_name do |alt_name|
40
+ yield alt_name
41
+ end
42
+ end
43
+ else
44
+ enum_for :each_name
45
+ end
46
+ end
47
+
48
+ # Enumerator over all names and abbreviations (including alternatives)
49
+ def each_string
50
+ if block_given?
51
+ yield @name
52
+ @abbrevs.each do |a|
53
+ yield a
54
+ end
55
+ @alternatives.each do |bn|
56
+ bn.each_string do |s|
57
+ yield s
58
+ end
59
+ end
60
+ else
61
+ enum_for :each_string
62
+ end
22
63
  end
23
64
 
24
65
  def to_s
25
- @osis_id.to_s
66
+ @name
67
+ end
68
+
69
+ # Convert the instance to an equivalent string representation
70
+ def dump
71
+ s = Kernel.format('%s: %s', @book_id, [@name, @abbrevs].flatten.join('|'))
72
+ [s, @alternatives.map(&:dump).map {|s| s.sub(/^.+?: /, '')}].flatten.join(', ')
73
+ end
74
+
75
+ def inspect
76
+ Kernel.format('#<%s %s>', self.class, dump.inspect)
77
+ end
78
+
79
+ def == other
80
+ other.respond_to?(:dump) && dump == other.dump
26
81
  end
27
82
 
28
83
  alias to_str to_s
29
84
 
85
+ class << self
86
+
87
+ # Helper method to create Bookname instances from a String
88
+ # @param s string to parse
89
+ # format: [book_id]: [full name]|[abbrev1]|[abbrev2]|...(, [alternative name]|[abbrev1],...]*
90
+ # @example Format
91
+ # Zeph: Zefanja|Zef, Zephanja|Zeph
92
+ # @example Code equivalent
93
+ # Bookname.new(book_id: :Zeph, name: 'Zefanja', abbrevs: ['Zef'], alternatives: Bookname.new(book_id: :Zeph, name: 'Zephanja', abbrevs: ['Zeph']))
94
+ def parse s
95
+ book_id, rest = s.split(/:\s*/).map(&:strip)
96
+ book_id = book_id.to_sym
97
+ org, *alternatives = rest.split(/,\s*/).map(&:strip)
98
+ name, *abbrevs = org.split('|').map(&:strip)
99
+ alternatives.map! do |s|
100
+ n, *a = s.split('|').map(&:strip)
101
+ Bookname.new(book_id: book_id, name: n, abbrevs: a)
102
+ end
103
+ Bookname.new(book_id: book_id, name: name, abbrevs: abbrevs, alternatives: alternatives)
104
+ end
105
+
106
+ end
107
+
30
108
  end
31
109
 
32
110
  end
@@ -3,18 +3,46 @@
3
3
 
4
4
  module Scripref
5
5
 
6
- # Constants of different orderings of bible books using standardized IDs
6
+ # Module to handle differend orderings of bible books using standardized IDs
7
7
  # (see https://wiki.crosswire.org/OSIS_Book_Abbreviations)
8
8
  module Bookorder
9
9
 
10
10
  # Canonical order (the default order without any apocryphal books)
11
- CANONICAL = %i[
12
- Gen Exod Lev Num Deut Josh Judg Ruth 1Sam 2Sam 1Kgs 2Kgs 1Chr 2Chr Ezra
13
- Neh Esth Job Ps Prov Eccl Song Isa Jer Lam Ezek Dan Hos Joel Amos Obad
14
- Jonah Mic Nah Hab Zeph Hag Zech Mal Matt Mark Luke John Acts Rom 1Cor
15
- 2Cor Gal Eph Phil Col 1Thess 2Thess 1Tim 2Tim Titus Phlm Heb Jas 1Pet
16
- 2Pet 1John 2John 3John Jude Rev
17
- ]
11
+ module Canonical
12
+
13
+ BOOK_IDS = %i[
14
+ Gen Exod Lev Num Deut Josh Judg Ruth 1Sam 2Sam 1Kgs 2Kgs 1Chr 2Chr Ezra
15
+ Neh Esth Job Ps Prov Eccl Song Isa Jer Lam Ezek Dan Hos Joel Amos Obad
16
+ Jonah Mic Nah Hab Zeph Hag Zech Mal Matt Mark Luke John Acts Rom 1Cor
17
+ 2Cor Gal Eph Phil Col 1Thess 2Thess 1Tim 2Tim Titus Phlm Heb Jas 1Pet
18
+ 2Pet 1John 2John 3John Jude Rev
19
+ ]
20
+
21
+ def book2num book_id
22
+ @book2num ||= BOOK_IDS.zip(1..).to_h
23
+ @book2num[book_id]
24
+ end
25
+
26
+ end
27
+
28
+ # Luther order (without any apocryphal books)
29
+ module Luther
30
+
31
+ BOOK_IDS = %i[
32
+ Gen Exod Lev Num Deut Josh Judg Ruth 1Sam 2Sam 1Kgs 2Kgs 1Chr 2Chr Ezra
33
+ Neh Esth Job Ps Prov Eccl Song Isa Jer Lam Ezek Dan Hos Joel Amos Obad
34
+ Jonah Mic Nah Hab Zeph Hag Zech Mal Matt Mark Luke John Acts Rom 1Cor
35
+ 2Cor Gal Eph Phil Col 1Thess 2Thess 1Tim 2Tim Titus Phlm 1Pet 2Pet 1John
36
+ 2John 3John Heb Jas Jude Rev
37
+ ]
38
+
39
+ def book2num book_id
40
+ @book2num ||= BOOK_IDS.zip(1..).to_h
41
+ @book2num[book_id]
42
+ end
43
+
44
+ end
45
+
18
46
  end
19
47
 
20
48
  end
@@ -8,34 +8,81 @@ module Scripref
8
8
  # Mixin for parsing references in English.
9
9
  module English
10
10
 
11
- book_names = <<-END.strip.split(/,\s*/)
12
- Genesis, Exodus, Leviticus, Numbers, Deuteronomy, Joshua, Judges,
13
- Ruth, 1 Samuel, 2 Samuel, 1 Kings, 2 Kings, 1 Chronicles,
14
- 2 Chronicles, Ezra, Nehemiah, Esther, Job, Psalms, Proverbs,
15
- Ecclesiastes, Song of Songs, Isaiah, Jeremiah, Lamentations,
16
- Ezekiel, Daniel, Hosea, Joel, Amos, Obadiah, Jonah, Micah, Nahum,
17
- Habakkuk, Zephaniah, Haggai, Zechariah, Malachi,
18
- Matthew, Mark, Luke, John, Acts, Romans, 1 Corinthians,
19
- 2 Corinthians, Galatians, Ephesians, Philippians, Colossians,
20
- 1 Thessalonians, 2 Thessalonians, 1 Timothy, 2 Timothy, Titus,
21
- Philemon, Hebrews, James, 1 Peter, 2 Peter, 1 John, 2 John, 3 John,
22
- Jude, Revelation
11
+ booknames = <<-END
12
+ Gen: Genesis|Gen
13
+ Exod: Exodus|Ex
14
+ Lev: Leviticus|Lev
15
+ Num: Numbers|Num
16
+ Deut: Deuteronomy|Deut
17
+ Josh: Joshua|Josh
18
+ Judg: Judges|Judg
19
+ Ruth: Ruth|Rth
20
+ 1Sam: 1 Samuel|1 Sam
21
+ 2Sam: 2 Samuel|2 Sam
22
+ 1Kgs: 1 Kings|1 Kgs
23
+ 2Kgs: 2 Kings|2 Kgs
24
+ 1Chr: 1 Chronicles|1 Chron
25
+ 2Chr: 2 Chronicles|2 Chron
26
+ Ezra: Ezra|Ezr
27
+ Neh: Nehemiah|Neh
28
+ Esth: Esther|Esth
29
+ Job: Job|Job
30
+ Ps: Psalms|Ps
31
+ Prov: Proverbs|Prov
32
+ Eccl: Ecclesiastes|Eccles
33
+ Song: Song of Songs|Song
34
+ Isa: Isaiah|Isa
35
+ Jer: Jeremiah|Jer
36
+ Lam: Lamentations|Lam
37
+ Ezek: Ezekiel|Ezek
38
+ Dan: Daniel|Dan
39
+ Hos: Hosea|Hos
40
+ Joel: Joel|Joel
41
+ Amos: Amos|Am
42
+ Obad: Obadiah|Obad
43
+ Jonah: Jonah|Jon
44
+ Mic: Micah|Mic
45
+ Nah: Nahum|Nah
46
+ Hab: Habakkuk|Hab
47
+ Zeph: Zephaniah|Zeph
48
+ Hag: Haggai|Hag
49
+ Zech: Zechariah|Zech
50
+ Mal: Malachi|Mal
51
+ Matt: Matthew|Matt
52
+ Mark: Mark|Mrk
53
+ Luke: Luke|Luk
54
+ John: John|John
55
+ Acts: Acts|Acts
56
+ Rom: Romans|Rom
57
+ 1Cor: 1 Corinthians|1 Cor
58
+ 2Cor: 2 Corinthians|2 Cor
59
+ Gal: Galatians|Gal
60
+ Eph: Ephesians|Eph
61
+ Phil: Philippians|Phil
62
+ Col: Colossians|Col
63
+ 1Thess: 1 Thessalonians|1 Thess
64
+ 2Thess: 2 Thessalonians|2 Thess
65
+ 1Tim: 1 Timothy|1 Tim
66
+ 2Tim: 2 Timothy|2 Tim
67
+ Titus: Titus|Tit
68
+ Phlm: Philemon|Philem
69
+ Heb: Hebrews|Heb
70
+ Jas: James|Jas
71
+ 1Pet: 1 Peter|1 Pet
72
+ 2Pet: 2 Peter|2 Pet
73
+ 1John: 1 John|1 Joh
74
+ 2John: 2 John|2 Joh
75
+ 3John: 3 John|3 Joh
76
+ Jude: Jude|Jud
77
+ Rev: Revelation|Rev
23
78
  END
24
79
 
25
- book_abbrevs = <<-END.strip.split(/,\s*/)
26
- Gen, Ex, Lev, Num, Deut, Josh, Judg, Rth, 1 Sam, 2 Sam, 1 Kgs, 2 Kgs,
27
- 1 Chron, 2 Chron, Ezr, Neh, Esth, Job, Ps, Prov, Eccles, Song, Isa,
28
- Jer, Lam, Ezek, Dan, Hos, Joel, Am, Obad, Jon, Mic, Nah, Hab, Zeph, Hag,
29
- Zech, Mal, Matt, Mrk, Luk, John, Acts, Rom, 1 Cor, 2 Cor, Gal, Eph, Phil,
30
- Col, 1 Thess, 2 Thess, 1 Tim, 2 Tim, Tit, Philem, Heb, Jas, 1 Pet, 2 Pet,
31
- 1 Joh, 2 Joh, 3 Joh, Jud, Rev
32
- END
33
-
34
- # Array of book names.
35
- BOOK_NAMES = Bookorder::CANONICAL.zip(book_names, book_abbrevs).map {|osis_book_id, names, abbrevs| Bookname.new(osis_id: osis_book_id, names: names, abbrevs: abbrevs)}
36
-
37
- # Map of OSIS book ID to instance of Bookname
38
- OSIS_BOOK_ID_TO_BOOK_NAME = Bookorder::CANONICAL.zip(BOOK_NAMES).map {|id, n| [id, n]}.to_h
80
+ # Mapping of OSIS book ID to instance of Bookname
81
+ BOOKNAMES_HASH = {}
82
+ booknames.each_line do |l|
83
+ bn = Bookname.parse(l)
84
+ BOOKNAMES_HASH[bn.book_id] = bn
85
+ end
39
86
 
40
87
  # Separator between chapter and verse.
41
88
  CV_SEPARATOR = ':'
@@ -77,9 +124,9 @@ module Scripref
77
124
  POSTFIX_MORE_FOLLOWING_VERSES_RE = /ff\b\s*/o
78
125
 
79
126
  # Check if book has only one chapter
80
- # @param osis_id OSIS-ID of the book
81
- def book_has_only_one_chapter? osis_id
82
- %i[Obad Phlm 2John 3John Jude].include?(osis_id)
127
+ # @param book_id OSIS-ID of the book
128
+ def book_has_only_one_chapter? book_id
129
+ %i[Obad Phlm 2John 3John Jude].include?(book_id)
83
130
  end
84
131
 
85
132
  # Regular expression to match punctuation marks
@@ -5,14 +5,14 @@ module Scripref
5
5
 
6
6
  class Formatter
7
7
 
8
- attr_accessor :bookformat, :cv_separator, :hyphen_separator, :pass_separator
8
+ attr_accessor :abbrev_level, :cv_separator, :hyphen_separator, :pass_separator
9
9
 
10
10
  # @param mods one or more modules to include
11
- # @param bookformat (:short use abbreviations, :long use full names of books)
12
- def initialize *mods, bookformat: :name
11
+ # @param abbrev_level if 0 full name, if >0 an abbreviation
12
+ def initialize *mods, abbrev_level: 0
13
13
  @mods = mods
14
14
  mods.each {|m| extend m}
15
- @bookformat = bookformat
15
+ @abbrev_level = abbrev_level
16
16
  end
17
17
 
18
18
  # Formats a reference (array of passages and maybe separators)
@@ -28,9 +28,9 @@ module Scripref
28
28
  end
29
29
 
30
30
  # Formats a book
31
- # @param osis_book_id OSIS-ID for book
32
- def format_book osis_book_id
33
- osis_book_id_to_book_name[osis_book_id].send @bookformat
31
+ # @param book_id OSIS-ID for book
32
+ def format_book book_id
33
+ booknames_hash[book_id].format(abbrev_level: abbrev_level)
34
34
  end
35
35
 
36
36
  # Formats a chapter
@@ -8,33 +8,81 @@ module Scripref
8
8
  # Mixin for parsing references in German.
9
9
  module German
10
10
 
11
- book_names = <<-END.strip.split(/,\s*/).map {|e| e.split('|')}
12
- 1. Mose, 2. Mose, 3. Mose, 4. Mose, 5. Mose, Josua, Richter, Ruth, 1. Samuel, 2. Samuel,
13
- 1. Könige, 2. Könige, 1. Chronika, 2. Chronika, Esra, Nehemia, Esther, Hiob, Psalm|Psalmen,
14
- Sprüche, Prediger, Hohelied, Jesaja, Jeremia, Klagelieder, Hesekiel, Daniel, Hosea, Joel,
15
- Amos, Obadja, Jona, Micha, Nahum, Habakuk, Zefanja|Zephanja, Haggai, Sacharja, Maleachi,
16
- Matthäus, Markus, Lukas, Johannes, Apostelgeschichte, Römer, 1. Korinther, 2. Korinther,
17
- Galater, Epheser, Philipper, Kolosser, 1. Thessalonicher, 2. Thessalonicher, 1. Timotheus,
18
- 2. Timotheus, Titus, Philemon, Hebräer, Jakobus, 1. Petrus, 2. Petrus, 1. Johannes,
19
- 2. Johannes, 3. Johannes, Judas, Offenbarung
11
+ booknames = <<-END
12
+ Gen: 1. Mose|1. Mos|1Mo|1M
13
+ Exod: 2. Mose|2. Mos|2Mo|2M
14
+ Lev: 3. Mose|3. Mos|3Mo|3M
15
+ Num: 4. Mose|4. Mos|4Mo|4M
16
+ Deut: 5. Mose|5. Mos|5Mo|5M
17
+ Josh: Josua|Jos
18
+ Judg: Richter|Ri
19
+ Ruth: Ruth|Ruth|Rt
20
+ 1Sam: 1. Samuel|1. Sam|1Sam|1Sm
21
+ 2Sam: 2. Samuel|2. Sam|2Sam|2Sm
22
+ 1Kgs: 1. Könige|1. Kön|1Kön|1Kö
23
+ 2Kgs: 2. Könige|2. Kön|2Kön|2Kö
24
+ 1Chr: 1. Chronika|1. Chr|1Chr|1Ch
25
+ 2Chr: 2. Chronika|2. Chr|2Chr|2Ch
26
+ Ezra: Esra|Esr
27
+ Neh: Nehemia|Neh
28
+ Esth: Esther|Est
29
+ Job: Hiob|Hi
30
+ Ps: Psalm|Ps, Psalmen
31
+ Prov: Sprüche|Spr
32
+ Eccl: Prediger|Pred
33
+ Song: Hohelied|Hohel|Hoh|Hl
34
+ Isa: Jesaja|Jes
35
+ Jer: Jeremia|Jer
36
+ Lam: Klagelieder|Klag
37
+ Ezek: Hesekiel|Hes
38
+ Dan: Daniel|Dan
39
+ Hos: Hosea|Hos
40
+ Joel: Joel|Joel
41
+ Amos: Amos|Amos|Am
42
+ Obad: Obadja|Obad|Ob
43
+ Jonah: Jona|Jona|Jon
44
+ Mic: Micha|Mich|Mi
45
+ Nah: Nahum|Nah
46
+ Hab: Habakuk|Hab
47
+ Zeph: Zefanja|Zef, Zephanja|Zeph
48
+ Hag: Haggai|Hag
49
+ Zech: Sacharja|Sach
50
+ Mal: Maleachi|Mal
51
+ Matt: Matthäus|Mat|Mt
52
+ Mark: Markus|Mar|Mr
53
+ Luke: Lukas|Luk|Lk
54
+ John: Johannes|Joh|Jh
55
+ Acts: Apostelgeschichte|Apg
56
+ Rom: Römer|Röm|Rö
57
+ 1Cor: 1. Korinther|1. Kor|1Ko
58
+ 2Cor: 2. Korinther|2. Kor|2Ko
59
+ Gal: Galater|Gal
60
+ Eph: Epheser|Eph
61
+ Phil: Philipper|Phil
62
+ Col: Kolosser|Kol
63
+ 1Thess: 1. Thessalonicher|1. Thes|1.Thes|1Thes|1Th
64
+ 2Thess: 2. Thessalonicher|2. Thes|2.Thes|2Thes|2Th
65
+ 1Tim: 1. Timotheus|1. Tim|1Tim
66
+ 2Tim: 2. Timotheus|2. Tim|2Tim
67
+ Titus: Titus|Tit
68
+ Phlm: Philemon|Philem|Phm
69
+ Heb: Hebräer|Heb
70
+ Jas: Jakobus|Jak
71
+ 1Pet: 1. Petrus|1. Pet|1Pet|1Pe
72
+ 2Pet: 2. Petrus|2. Pet|2Pet|2Pe
73
+ 1John: 1. Johannes|1. Joh|1Joh|1Jo
74
+ 2John: 2. Johannes|2. Joh|2Joh|2Jo
75
+ 3John: 3. Johannes|3. Joh|3Joh|3Jo
76
+ Jude: Judas|Jud
77
+ Rev: Offenbarung|Off
20
78
  END
21
79
 
22
- book_abbrevs = <<-END.strip.split(/,\s*/).map {|e| e.split('|')}
23
- 1. Mos|1Mo|1M, 2. Mos|2Mo|2M, 3. Mos|3Mo|3M, 4. Mos|4Mo|4M, 5. Mos|5Mo|5M, Jos, Ri,
24
- Ruth|Rt, 1. Sam|1Sam|1Sm, 2. Sam|2Sam|2Sm, 1. Kön|1Kön|1Kö, 2. Kön|2Kön|2Kö,
25
- 1. Chr|1Chr|1Ch, 2. Chr|2Chr|2Ch, Esr, Neh, Est, Hi, Ps, Spr, Pred,
26
- Hohel|Hoh|Hl, Jes, Jer, Klag, Hes, Dan, Hos, Joel, Amos|Am, Obad|Ob,
27
- Jona|Jon, Mich|Mi, Nah, Hab, Zef, Hag, Sach, Mal, Mat|Mt, Mar|Mr, Luk|Lk,
28
- Joh|Jh, Apg, Röm|Rö, 1. Kor|1Ko, 2. Kor|2Ko, Gal, Eph, Phil, Kol,
29
- 1. Thes|1.Thes|1Thes|1Th, 2. Thes|2.Thes|2Thes|2Th, 1. Tim|1Tim, 2. Tim|2Tim, Tit, Philem|Phm, Heb, Jak, 1. Pet|1Pet|1Pe, 2. Pet|2Pet|2Pe,
30
- 1. Joh|1Joh|1Jo, 2. Joh|2Joh|2Jo, 3. Joh|3Joh|3Jo, Jud, Off
31
- END
32
-
33
- # Array of book names.
34
- BOOK_NAMES = Bookorder::CANONICAL.zip(book_names, book_abbrevs).map {|osis_book_id, names, abbrevs| Bookname.new(osis_id: osis_book_id, names: names, abbrevs: abbrevs)}
35
-
36
- # Map of OSIS book ID to instance of Bookname
37
- OSIS_BOOK_ID_TO_BOOK_NAME = Bookorder::CANONICAL.zip(BOOK_NAMES).map {|id, n| [id, n]}.to_h
80
+ # Mapping of OSIS book ID to instance of Bookname
81
+ BOOKNAMES_HASH = {}
82
+ booknames.each_line do |l|
83
+ bn = Bookname.parse(l)
84
+ BOOKNAMES_HASH[bn.book_id] = bn
85
+ end
38
86
 
39
87
  # Separator between chapter and verse.
40
88
  CV_SEPARATOR = ','
@@ -76,9 +124,9 @@ module Scripref
76
124
  POSTFIX_MORE_FOLLOWING_VERSES_RE = /ff\b\s*/o
77
125
 
78
126
  # Check if book has only one chapter
79
- # @param osis_id OSIS-ID of the book
80
- def book_has_only_one_chapter? osis_id
81
- %i[Obad Phlm 2John 3John Jude].include?(osis_id)
127
+ # @param book_id OSIS-ID of the book
128
+ def book_has_only_one_chapter? book_id
129
+ %i[Obad Phlm 2John 3John Jude].include?(book_id)
82
130
  end
83
131
 
84
132
  # Regular expression to match punctuation marks
@@ -6,7 +6,7 @@ require 'strscan'
6
6
 
7
7
  module Scripref
8
8
 
9
- class Parser < StringScanner
9
+ class Parser
10
10
 
11
11
  attr_reader :error
12
12
 
@@ -21,12 +21,28 @@ module Scripref
21
21
  # Parsing a string of a scripture reference
22
22
  # @param str string to parse
23
23
  def parse str
24
- self.string = str
24
+ @scanner = StringScanner.new(str)
25
25
  @result = []
26
26
  @error = nil
27
27
  start
28
28
  end
29
29
 
30
+ def format_error
31
+ if error
32
+ format("%s\n%s\n%s^", error, @scanner.string, ' ' * @scanner.pointer)
33
+ else
34
+ ''
35
+ end
36
+ end
37
+
38
+ def inspect
39
+ "#<#{self.class} #{@mods.inspect}>"
40
+ end
41
+
42
+ alias << parse
43
+
44
+ private
45
+
30
46
  # start of parsing grammer
31
47
  def start
32
48
  @text = ''
@@ -35,14 +51,14 @@ module Scripref
35
51
 
36
52
  # try to parse first book
37
53
  def b1
38
- s = scan(book_re) or return nil
54
+ s = @scanner.scan(book_re) or return nil
39
55
  @text << s
40
- @b1 = @b2 = abbrev2osis_book_id(s)
56
+ @b1 = @b2 = str2book_id(s)
41
57
  @c1 = @v1 = @c2 = @v2 = nil
42
58
 
43
59
  if pass_sep
44
60
  b1 or give_up 'EOS or book expected!'
45
- elsif check(Regexp.new(chapter_re.source + cv_sep_re.source))
61
+ elsif @scanner.check(Regexp.new(chapter_re.source + cv_sep_re.source))
46
62
  @c1 = @v1 = nil
47
63
  @c2 = @v2 = nil
48
64
  c1
@@ -60,7 +76,7 @@ module Scripref
60
76
 
61
77
  # try parse first chapter
62
78
  def c1
63
- s = scan(chapter_re) or return nil
79
+ s = @scanner.scan(chapter_re) or return nil
64
80
  @text << s
65
81
  @c1 = @c2 = s.to_i
66
82
  @v1 = @v2 = nil
@@ -78,7 +94,7 @@ module Scripref
78
94
 
79
95
  # try to parse first verse
80
96
  def v1
81
- s = scan(verse_re) or return nil
97
+ s = @scanner.scan(verse_re) or return nil
82
98
  @text << s
83
99
  @v1 = @v2 = s.to_i
84
100
 
@@ -92,7 +108,7 @@ module Scripref
92
108
 
93
109
  if hyphen
94
110
  b2 or (
95
- if check(Regexp.new(chapter_re.source + cv_sep_re.source))
111
+ if @scanner.check(Regexp.new(chapter_re.source + cv_sep_re.source))
96
112
  c2
97
113
  else
98
114
  v2 or give_up 'Chapter or verse expected!'
@@ -108,14 +124,14 @@ module Scripref
108
124
 
109
125
  # try to parse second book
110
126
  def b2
111
- s = scan(book_re) or return nil
127
+ s = @scanner.scan(book_re) or return nil
112
128
  @text << s
113
- @b2 = abbrev2osis_book_id(s)
129
+ @b2 = str2book_id(s)
114
130
  @c2 = @v2 = nil
115
131
 
116
132
  if pass_sep
117
133
  b1 or give_up 'EOS or book expected!'
118
- elsif check(Regexp.new(chapter_re.source + cv_sep_re.source))
134
+ elsif @scanner.check(Regexp.new(chapter_re.source + cv_sep_re.source))
119
135
  c2
120
136
  else
121
137
  if book_has_only_one_chapter?(@b2)
@@ -129,7 +145,7 @@ module Scripref
129
145
 
130
146
  # try to parse second chapter
131
147
  def c2
132
- s = scan(chapter_re) or return nil
148
+ s = @scanner.scan(chapter_re) or return nil
133
149
  @text << s
134
150
  @c2 = s.to_i
135
151
 
@@ -144,7 +160,7 @@ module Scripref
144
160
 
145
161
  # try to parse second verse
146
162
  def v2
147
- s = scan(verse_re) or return nil
163
+ s = @scanner.scan(verse_re) or return nil
148
164
  @text << s
149
165
  @v2 = s.to_i
150
166
 
@@ -163,16 +179,16 @@ module Scripref
163
179
 
164
180
  # try to parse <tt>end of string</tt>
165
181
  def epsilon
166
- if eos?
182
+ if @scanner.eos?
167
183
  push_passage
168
184
  return @result
169
185
  end
170
186
  nil
171
187
  end
172
188
 
173
- # try to parse separator or chapter and verse
189
+ # try to parse separator of chapter and verse
174
190
  def cv_sep
175
- if s = scan(cv_sep_re)
191
+ if s = @scanner.scan(cv_sep_re)
176
192
  @text << s
177
193
  s
178
194
  else
@@ -182,7 +198,7 @@ module Scripref
182
198
 
183
199
  # try to parse hyphen
184
200
  def hyphen
185
- if s = scan(hyphen_re)
201
+ if s = @scanner.scan(hyphen_re)
186
202
  @text << s
187
203
  s
188
204
  else
@@ -192,7 +208,7 @@ module Scripref
192
208
 
193
209
  # try to parse separator between passages
194
210
  def pass_sep
195
- if s = scan(pass_sep_re)
211
+ if s = @scanner.scan(pass_sep_re)
196
212
  push_passage
197
213
  @result << PassSep.new(s)
198
214
  s
@@ -203,7 +219,7 @@ module Scripref
203
219
 
204
220
  # try to parse verse separator
205
221
  def verse_sep
206
- if s = scan(verse_sep_re)
222
+ if s = @scanner.scan(verse_sep_re)
207
223
  push_passage
208
224
  @result << VerseSep.new(s)
209
225
  s
@@ -214,7 +230,7 @@ module Scripref
214
230
 
215
231
  # try to parse addons for verses
216
232
  def verse_addon
217
- if s = scan(verse_addon_re)
233
+ if s = @scanner.scan(verse_addon_re)
218
234
  @text << s
219
235
  s.to_sym
220
236
  else
@@ -224,7 +240,7 @@ module Scripref
224
240
 
225
241
  # try to parse postfixes for verse
226
242
  def verse_postfix
227
- s = (scan(postfix_one_following_verse_re) or scan(postfix_more_following_verses_re))
243
+ s = (@scanner.scan(postfix_one_following_verse_re) or @scanner.scan(postfix_more_following_verses_re))
228
244
  if s
229
245
  @text << s
230
246
  s.to_sym
@@ -239,48 +255,43 @@ module Scripref
239
255
  @a1 = @a2 = nil
240
256
  end
241
257
 
242
- def abbrev2osis_book_id str
258
+ def str2book_id str
243
259
  s = str.strip
244
260
  s.sub! /\.$/, ''
245
- str2osis_book_id(s) or str2osis_book_id(abbrev2book(s))
261
+ str2book_id_cache(s) or calculate_str2book_id(s)
246
262
  end
247
263
 
248
- def abbrev2book str
264
+ def calculate_str2book_id str
249
265
  s = str.strip
250
266
  s.sub! /\.$/, ''
251
- @books_str ||= ('#' << book_names.map(&:names).flatten.join('#') << '#')
267
+ @books_str ||= ('#' << each_bookname.map(&:each_name).flat_map(&:to_a).join('#') << '#')
252
268
  pattern = s.chars.map {|c| Regexp.escape(c) << '[^#]*'}.join
253
269
  re = /(?<=#)#{pattern}(?=#)/
254
270
  names = @books_str.scan(re)
255
- uniq_numbers = names.map {|n| str2osis_book_id(n)}.uniq
271
+ uniq_numbers = names.map {|n| str2book_id_cache(n)}.uniq
256
272
  if uniq_numbers.size != 1
257
- unscan
273
+ @scanner.unscan
258
274
  give_up format("Abbreviation %s is ambiguous it matches %s!", s, names.join(', '))
259
275
  end
260
- names.first
276
+ book_id = str2book_id_cache(names.first)
277
+ @str2book_id_cache[s] = book_id
278
+ book_id
261
279
  end
262
280
 
263
- def init_str2osis_book_id
264
- unless @str2osis_book_id
265
- @str2osis_book_id = {}
266
- book_names.each do |bn|
267
- bn.names.each do |n|
268
- @str2osis_book_id[n] = bn.osis_id
269
- end
270
- bn.abbrevs.each do |n|
271
- @str2osis_book_id[n] = bn.osis_id
281
+ def init_str2book_id_cache
282
+ unless @str2book_id_cache
283
+ @str2book_id_cache = {}
284
+ each_bookname do |bn|
285
+ bn.each_string do |s|
286
+ @str2book_id_cache[s] = bn.book_id
272
287
  end
273
288
  end
274
289
  end
275
290
  end
276
291
 
277
- def str2osis_book_id str
278
- init_str2osis_book_id
279
- @str2osis_book_id[str]
280
- end
281
-
282
- def inspect
283
- "#<#{self.class} #{@mods.inspect}>"
292
+ def str2book_id_cache str
293
+ init_str2book_id_cache
294
+ @str2book_id_cache[str]
284
295
  end
285
296
 
286
297
  def give_up msg
@@ -288,16 +299,6 @@ module Scripref
288
299
  fail ParserError, format_error
289
300
  end
290
301
 
291
- def format_error
292
- if error
293
- format("%s\n%s\n%s^", error, string, ' ' * pointer)
294
- else
295
- ''
296
- end
297
- end
298
-
299
- alias << parse
300
-
301
302
  end
302
303
 
303
304
  class ParserError < RuntimeError; end
@@ -5,70 +5,17 @@ module Scripref
5
5
 
6
6
  Passage = Struct.new(:text, :b1, :c1, :v1, :b2, :c2, :v2, :a1, :a2, keyword_init: true) do
7
7
 
8
- include Comparable
9
-
10
8
  def to_a
11
9
  [b1, c1, v1, b2, c2, v2]
12
10
  end
13
11
 
14
- def <=> other
15
- return unless other.kind_of? Passage
16
- self.to_numeric_array <=> other.to_numeric_array
17
- end
18
-
19
- # Returns true if the instance and the given passage overlap.
20
- # That means both has at least one verse in common.
21
- def overlap? passage
22
- fail ArgumentError, 'value must be a passage' unless passage.kind_of? Passage
23
- a = self.to_numeric_array
24
- b = passage.to_numeric_array
25
- [a[0..2] <=> b[3..5], b[0..2] <=> a[3..5]].max < 1
26
- end
27
-
28
- # Returns an array of b1, c1, v1
29
- def start
30
- [b1, c1, v1]
31
- end
32
-
33
- # Returns an array of b2, c2, v2
34
- def end
35
- [b2, c2, v2]
36
- end
37
-
38
- def to_numeric_array max: 999, ff: 3
39
- _b1 = Passage.book_id2num[b1]
40
- _c1 = c1 || 1
41
- _v1 = v1 || 1
42
- _b2 = Passage.book_id2num[b2]
43
- _c2 = c2 || max
44
- _v2 = v2 || max
45
- if _v2 == :f
46
- _v2 = _v1 + 1
47
- end
48
- if _v2 == :ff
49
- _v2 = _v1 + ff
50
- end
51
- [_b1, _c1, _v1, _b2, _c2, _v2]
12
+ def == other
13
+ return false unless other.kind_of? Passage
14
+ to_a == other.to_a
52
15
  end
53
16
 
54
17
  alias to_s text
55
18
 
56
- @book_id2num = {}
57
- osis_book_ids = %i[
58
- Gen Exod Lev Num Deut Josh Judg Ruth 1Sam 2Sam 1Kgs 2Kgs 1Chr 2Chr Ezra
59
- Neh Esth Job Ps Prov Eccl Song Isa Jer Lam Ezek Dan Hos Joel Amos Obad
60
- Jonah Mic Nah Hab Zeph Hag Zech Mal Matt Mark Luke John Acts Rom 1Cor
61
- 2Cor Gal Eph Phil Col 1Thess 2Thess 1Tim 2Tim Titus Phlm Heb Jas 1Pet
62
- 2Pet 1John 2John 3John Jude Rev
63
- ]
64
- osis_book_ids.each_with_index do |book_id, i|
65
- @book_id2num[book_id] = i+1
66
- end
67
-
68
- class << self
69
- attr_reader :book_id2num
70
- end
71
-
72
19
  end
73
20
 
74
21
  end
@@ -71,6 +71,8 @@ module Scripref
71
71
  @reference_re = Regexp.compile(re_parts.join, nil)
72
72
  end
73
73
 
74
+ private
75
+
74
76
  def fix_scanner_and_results scanner
75
77
  text = scanner[1]
76
78
  ref = scanner[2]
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Scripref
5
+
6
+ class Sorter
7
+
8
+ def initialize *mods
9
+ @mods = mods
10
+ mods.each {|m| extend m}
11
+ end
12
+
13
+ def sort *references
14
+ passages = references.flatten.select {|e| e.kind_of? Scripref::Passage}
15
+ passages.sort do |p1, p2|
16
+ signum(p1, p2)
17
+ end
18
+ end
19
+
20
+ alias << sort
21
+
22
+ # Mixin to sort ascending by start verse and desending by end verse of passages
23
+ module SortUpDown
24
+ def signum pass1, pass2
25
+ a, b = passage2arr(pass1), passage2arr(pass2)
26
+ a[0, 3] + b[3, 3] <=> b[0, 3] + a[3, 3]
27
+ end
28
+ end
29
+
30
+ # Mixin to sort ascending by start verse and ascending by end verse of passages
31
+ module SortUpUp
32
+ def signum pass1, pass2
33
+ a, b = passage2arr(pass1), passage2arr(pass2)
34
+ a <=> b
35
+ end
36
+ end
37
+
38
+ # Default sorting
39
+
40
+ include SortUpDown
41
+
42
+ private
43
+
44
+ def passage2arr pass
45
+ b1 = book2num(pass.b1)
46
+ b2 = book2num(pass.b2)
47
+ [b1, pass.c1 || 1, pass.v1 || 1, b2, pass.c2 || Float::INFINITY, pass.v2 || Float::INFINITY]
48
+ end
49
+
50
+ end
51
+
52
+ end
data/lib/scripref.rb CHANGED
@@ -5,7 +5,7 @@ require 'delegate'
5
5
 
6
6
  module Scripref
7
7
 
8
- VERSION = '1.2.2'
8
+ VERSION = '2.0.0'
9
9
 
10
10
  require_relative 'scripref/bookname'
11
11
  require_relative 'scripref/bookorder'
@@ -15,6 +15,7 @@ module Scripref
15
15
  require_relative 'scripref/parser'
16
16
  require_relative 'scripref/passage'
17
17
  require_relative 'scripref/processor'
18
+ require_relative 'scripref/sorter'
18
19
 
19
20
  class Token < DelegateClass(String)
20
21
  def initialize *args
@@ -8,15 +8,23 @@ class TestBookname < Test::Unit::TestCase
8
8
  include Scripref
9
9
 
10
10
  def setup
11
- @zef = Bookname.new(osis_id: :Zeph, names: %w(Zefanja Zephanja), abbrevs: %w(Zef Zefan Zeph Zephan))
11
+ @zef = Bookname.new(book_id: :Zeph, name: 'Zefanja', abbrevs: %w(Zefan Zef), alternatives: Bookname.new(book_id: :Zeph, name: 'Zephanja', abbrevs: 'Zeph'))
12
12
  end
13
13
 
14
- def test_name
15
- assert_equal 'Zefanja', @zef.name
14
+ def test_each_name
15
+ assert_equal %w(Zefanja Zephanja), @zef.each_name.to_a
16
16
  end
17
17
 
18
- def test_abbrev
19
- assert_equal 'Zef', @zef.abbrev
18
+ def test_each_string
19
+ assert_equal %w(Zefanja Zefan Zef Zephanja Zeph), @zef.each_string.to_a
20
+ end
21
+
22
+ def test_parse
23
+ assert_equal @zef, Bookname.parse('Zeph: Zefanja|Zefan|Zef, Zephanja|Zeph')
24
+ end
25
+
26
+ def test_dump
27
+ assert_equal 'Zeph: Zefanja|Zefan|Zef, Zephanja|Zeph', @zef.dump
20
28
  end
21
29
 
22
30
  end
data/test/test_english.rb CHANGED
@@ -13,7 +13,7 @@ class TestEnglish < Test::Unit::TestCase
13
13
  end
14
14
 
15
15
  def test_size_of_book_array
16
- assert_equal 66, English::BOOK_NAMES.size
16
+ assert_equal 66, English::BOOKNAMES_HASH.size
17
17
  end
18
18
 
19
19
  def test_book_re
@@ -32,20 +32,20 @@ class TestEnglish < Test::Unit::TestCase
32
32
  assert_match book_re, 'Rev'
33
33
  end
34
34
 
35
- def test_book2osis_id
36
- assert_osis_book_id :Gen, 'Genesis'
37
- assert_osis_book_id :Matt, 'Matthew'
38
- assert_osis_book_id :Rev, 'Revelation'
39
- assert_osis_book_id :Gen, 'Gen'
40
- assert_osis_book_id :Gen, 'Ge'
41
- assert_osis_book_id :'2Tim', '2 Tim'
42
- assert_osis_book_id :'2Tim', '2Tim'
43
- assert_osis_book_id :'2Tim', '2Tm'
44
- assert_osis_book_id :Matt, 'Mat'
45
- assert_osis_book_id :Rev, 'Rev'
35
+ def test_book2book_id
36
+ assert_book_id :Gen, 'Genesis'
37
+ assert_book_id :Matt, 'Matthew'
38
+ assert_book_id :Rev, 'Revelation'
39
+ assert_book_id :Gen, 'Gen'
40
+ assert_book_id :Gen, 'Ge'
41
+ assert_book_id :'2Tim', '2 Tim'
42
+ assert_book_id :'2Tim', '2Tim'
43
+ assert_book_id :'2Tim', '2Tm'
44
+ assert_book_id :Matt, 'Mat'
45
+ assert_book_id :Rev, 'Rev'
46
46
  end
47
47
 
48
- def assert_osis_book_id id, str
48
+ def assert_book_id id, str
49
49
  assert_equal id, @parser.parse(str).first.b1
50
50
  end
51
51
 
@@ -170,7 +170,8 @@ class TestFormatter < Test::Unit::TestCase
170
170
 
171
171
  def test_two_refs_with_book_with_only_one_chapter
172
172
  text = 'Obadja 3.5'
173
- assert_formated_text_for_ast text, [pass(text: text, b1: :Obad, c1: 1, v1: 3, b2: :Obad, c2: 1, v2: 3), pass(b1: :Obad, c1: 1, v1: 5, b2: :Obad, c2: 1, v2: 5)]
173
+ t1, t2 = text.split(dot)
174
+ assert_formated_text_for_ast text, [pass(text: t1, b1: :Obad, c1: 1, v1: 3, b2: :Obad, c2: 1, v2: 3), dot, pass(text: t2, b1: :Obad, c1: 1, v1: 5, b2: :Obad, c2: 1, v2: 5)]
174
175
  end
175
176
 
176
177
  ######################################################################
@@ -261,18 +262,12 @@ class TestFormatter < Test::Unit::TestCase
261
262
  ######################################################################
262
263
 
263
264
  def test_formatting_with_book_abbrevs
264
- @german_formatter.bookformat = :abbrev
265
+ @german_formatter.abbrev_level = 1
265
266
  text = 'Mat 3,4; Mar; Joh 3,16'
266
267
  t1, t2, t3 = text.split(semi)
267
268
  assert_formated_text_for_ast text, [pass(text: t1, b1: :Matt, c1: 3, v1: 4, b2: :Matt, c2: 3, v2: 4), semi, pass(text: t2, b1: :Mark, b2: :Mark), semi, pass(text: t3, b1: :John, c1: 3, v1: 16, b2: :John, c2: 3, v2: 16)]
268
269
  end
269
270
 
270
- def test_exception_for_unhandled_bookformat
271
- assert_raise NoMethodError do
272
- @german_formatter.bookformat = :unknown
273
- @german_formatter.format [pass(text: 1, b1: :Exod, c1: 3, v1: 4, b2: :Deut, c2: 6, v2: 7)]
274
- end
275
- end
276
271
  private
277
272
 
278
273
  def assert_formated_text_for_ast text, ast
data/test/test_german.rb CHANGED
@@ -13,7 +13,7 @@ class TestGerman < Test::Unit::TestCase
13
13
  end
14
14
 
15
15
  def test_size_of_book_array
16
- assert_equal 66, German::BOOK_NAMES.size
16
+ assert_equal 66, German::BOOKNAMES_HASH.size
17
17
  end
18
18
 
19
19
  def test_book_re
@@ -32,19 +32,19 @@ class TestGerman < Test::Unit::TestCase
32
32
  assert_match book_re, 'Off'
33
33
  end
34
34
 
35
- def test_book2osis_id
36
- assert_osis_book_id :Gen, '1. Mose'
37
- assert_osis_book_id :Matt, 'Matthäus'
38
- assert_osis_book_id :Rev, 'Offenbarung'
39
- assert_osis_book_id :Gen, '1. Mo'
40
- assert_osis_book_id :Gen, '1.Mo'
41
- assert_osis_book_id :Gen, '1M'
42
- assert_osis_book_id :Matt, 'Mat'
43
- assert_osis_book_id :Phil, 'Phil'
44
- assert_osis_book_id :Rev, 'Off'
35
+ def test_book2book_id
36
+ assert_book_id :Gen, '1. Mose'
37
+ assert_book_id :Matt, 'Matthäus'
38
+ assert_book_id :Rev, 'Offenbarung'
39
+ assert_book_id :Gen, '1. Mo'
40
+ assert_book_id :Gen, '1.Mo'
41
+ assert_book_id :Gen, '1M'
42
+ assert_book_id :Matt, 'Mat'
43
+ assert_book_id :Phil, 'Phil'
44
+ assert_book_id :Rev, 'Off'
45
45
  end
46
46
 
47
- def assert_osis_book_id id, str
47
+ def assert_book_id id, str
48
48
  @parser ||= Scripref::Parser.new(Scripref::German)
49
49
  assert_equal id, @parser.parse(str).first.b1
50
50
  end
data/test/test_parser.rb CHANGED
@@ -333,6 +333,17 @@ class TestParser < Test::Unit::TestCase
333
333
  assert_parsed_ast_for_text [pass(text: text, b1: :Ps, c1: 23, v1: 6, b2: :Ps, c2: 23, v2: 6)], text
334
334
  end
335
335
 
336
+ def test_alternatives
337
+ # In German Zephanja is alternative name for Zefanja
338
+ a = pass(b1: :Zeph, c1: 2, b2: :Zeph, c2: 2).to_a
339
+ assert_equal a, @parser.parse('Zefanja 2').first.to_a
340
+ assert_equal a, @parser.parse('Zefa 2').first.to_a
341
+ assert_equal a, @parser.parse('Zef 2').first.to_a
342
+ assert_equal a, @parser.parse('Zephanja 2').first.to_a
343
+ assert_equal a, @parser.parse('Zepha 2').first.to_a
344
+ assert_equal a, @parser.parse('Zeph 2').first.to_a
345
+ end
346
+
336
347
  private
337
348
 
338
349
  def assert_equal_passage expected, actual
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'test_helper'
5
+
6
+ class TestSorter < Test::Unit::TestCase
7
+
8
+ include Scripref
9
+ include Test::Helper
10
+
11
+ def setup
12
+ @john_1 = pass(b1: :John, c1: 1, b2: :John, c2: 1)
13
+ @john_1_1_3 = pass(b1: :John, c1: 1, v1: 1, b2: :John, c2: 1, v2: 3)
14
+ @john_1_1_18 = pass(b1: :John, c1: 1, v1: 1, b2: :John, c2: 1, v2: 18)
15
+ @john_2 = pass(b1: :John, c1: 2, b2: :John, c2: 2)
16
+ @heb_9 = pass(b1: :Heb, c1: 9, b2: :Heb, c2: 9)
17
+ @jas_1 = pass(b1: :Jas, c1: 1, b2: :Jas, c2: 1)
18
+ @pet_1 = pass(b1: :'1Pet', c1: 1, b2: :'1Pet', c2: 1)
19
+ end
20
+
21
+ def test_canonical_default
22
+ sorter = Sorter.new(Bookorder::Canonical)
23
+ assert_equal [@john_1, @heb_9, @jas_1, @pet_1], sorter.sort([@heb_9, @pet_1, @jas_1, @john_1])
24
+ assert_equal [@john_1_1_18, @john_1_1_3], sorter.sort([@john_1_1_3, @john_1_1_18])
25
+ assert_equal [@john_1, @john_1_1_18, @john_1_1_3, @john_2], sorter.sort([@john_1, @john_1_1_3, @john_2, @john_1_1_18])
26
+ end
27
+
28
+ def test_canonical_sort_up_up
29
+ sorter = Sorter.new(Bookorder::Canonical, Sorter::SortUpUp)
30
+ assert_equal [@john_1_1_3, @john_1_1_18], sorter.sort([@john_1_1_3, @john_1_1_18])
31
+ assert_equal [@john_1_1_3, @john_1_1_18, @john_1, @john_2], sorter.sort([@john_1, @john_1_1_3, @john_2, @john_1_1_18])
32
+ end
33
+
34
+ def test_luther_default
35
+ sorter = Sorter.new(Bookorder::Luther)
36
+ assert_equal [@john_1, @pet_1, @heb_9, @jas_1], sorter.sort([@heb_9, @pet_1, @jas_1, @john_1])
37
+ assert_equal [@john_1_1_18, @john_1_1_3], sorter.sort([@john_1_1_3, @john_1_1_18])
38
+ assert_equal [@john_1, @john_1_1_18, @john_1_1_3, @john_2], sorter.sort([@john_1, @john_1_1_3, @john_2, @john_1_1_18])
39
+ end
40
+
41
+ def test_luther_sort_up_up
42
+ sorter = Sorter.new(Bookorder::Luther, Sorter::SortUpUp)
43
+ assert_equal [@john_1, @pet_1, @heb_9, @jas_1], sorter.sort([@heb_9, @pet_1, @jas_1, @john_1])
44
+ assert_equal [@john_1_1_3, @john_1_1_18], sorter.sort([@john_1_1_3, @john_1_1_18])
45
+ assert_equal [@john_1_1_3, @john_1_1_18, @john_1, @john_2], sorter.sort([@john_1, @john_1_1_3, @john_2, @john_1_1_18])
46
+ end
47
+
48
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scripref
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Friedrich
@@ -87,6 +87,7 @@ files:
87
87
  - lib/scripref/passage.rb
88
88
  - lib/scripref/pipelining.rb
89
89
  - lib/scripref/processor.rb
90
+ - lib/scripref/sorter.rb
90
91
  - regtest/formatter.rb
91
92
  - regtest/formatter.yml
92
93
  - regtest/parser.rb
@@ -101,9 +102,9 @@ files:
101
102
  - test/test_helper.rb
102
103
  - test/test_integration.rb
103
104
  - test/test_parser.rb
104
- - test/test_passage.rb
105
105
  - test/test_pipelining.rb
106
106
  - test/test_processor.rb
107
+ - test/test_sorter.rb
107
108
  homepage: https://github.com/janfri/scripref
108
109
  licenses:
109
110
  - MIT
data/test/test_passage.rb DELETED
@@ -1,91 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- require_relative 'test_helper'
5
-
6
- class TestPassage < Test::Unit::TestCase
7
-
8
- include Scripref
9
- include Test::Helper
10
-
11
- def setup
12
- @parser = Parser.new(German)
13
- end
14
-
15
- def test_to_a
16
- pass = @parser.parse('Mr 1,2-Luk 3,4').first
17
- assert_equal [:Mark, 1, 2, :Luke, 3, 4], pass.to_a
18
- end
19
-
20
- def test_spaceship_operator
21
- ast = @parser.parse('Mar 2,3; Joh 1,5')
22
- p1, p2 = ast[0], ast[2]
23
- assert_nil p1 <=> :other_value
24
- assert_nil :other_value <=> p1
25
- assert_equal (-1), p1 <=> p2
26
- assert_equal 0, p1 <=> p1
27
- assert_equal 1, p2 <=> p1
28
- end
29
-
30
- def test_comparable_with_sort
31
- ast = @parser.parse('Joh 8,1-9,11; 8,2-9,12; 8,2-9,11; 8,1-9,12; Joh 8')
32
- passages = ast.grep(Passage)
33
- expect = ['Joh 8',
34
- 'Joh 8,1-9,11',
35
- '8,1-9,12',
36
- '8,2-9,11',
37
- '8,2-9,12']
38
- assert_equal expect, passages.sort.map(&:text)
39
-
40
- 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')
41
- passages = ast.grep(Passage)
42
- formatter = Formatter.new(German)
43
- expect = ['Markus 1,1',
44
- 'Markus 1,1f',
45
- 'Markus 1,1ff',
46
- 'Markus 1',
47
- 'Markus 1,1-2,2',
48
- 'Markus 1-2',
49
- 'Markus',
50
- 'Markus 1,1-Lukas 2,2',
51
- 'Markus 1-Lukas 2',
52
- 'Markus-Lukas',
53
- 'Markus 1,2']
54
- assert_equal expect, passages.sort.map {|e| formatter << e}
55
- end
56
-
57
- def test_overlap
58
- a = @parser.parse('Joh 8,1-9').first
59
- b = @parser.parse('Joh 8,8-11').first
60
- c = @parser.parse('Joh 8,12-15').first
61
- d = @parser.parse('Joh 8,15-18').first
62
- e = @parser.parse('Joh 8').first
63
- assert_overlap a, a
64
- assert_overlap a, b
65
- assert_not_overlap b, c
66
- assert_overlap c, d
67
- assert_overlap d, e
68
- end
69
-
70
- def test_start
71
- p = pass(text: '', b1: :Gen, c1: 2, v1: 3, b2: :Num, c2: 5, v2: 6)
72
- assert_equal [:Gen, 2, 3], p.start
73
- end
74
-
75
- def test_end
76
- p = pass(text: '', b1: :Gen, c1: 2, v1: 3, b2: :Num, c2: 5, v2: 6)
77
- assert_equal [:Num, 5, 6], p.end
78
- end
79
-
80
- protected
81
-
82
- def assert_overlap a, b
83
- assert a.overlap?(b)
84
- assert b.overlap?(a)
85
- end
86
-
87
- def assert_not_overlap a, b
88
- assert !a.overlap?(b)
89
- assert !b.overlap?(a)
90
- end
91
- end