pericope 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/pericope.rb CHANGED
@@ -2,28 +2,45 @@ require 'yaml'
2
2
  require 'pericope/version'
3
3
 
4
4
  class Pericope
5
- attr_reader :original_string, :book, :book_name, :book_chapter_count, :book_has_chapters, :ranges, :index
5
+ attr_reader :book,
6
+ :book_chapter_count,
7
+ :book_name,
8
+ :index,
9
+ :original_string,
10
+ :ranges
6
11
 
7
12
 
8
13
 
9
- def initialize(match)
10
- match = Pericope.match_one(match) if match.is_a?(String)
11
- raise "no pericope found in input" unless match.is_a?(MatchData)
12
-
13
- @original_string = match.to_s
14
- @index = match.begin(0)
15
- @book = match.instance_variable_get("@book")
16
- @book_name = Pericope.book_names[@book-1]
17
- @book_chapter_count = Pericope.book_chapter_counts[@book-1]
18
- @book_has_chapters = (book_chapter_count > 1)
19
- reference = normalize_reference(match[1])
20
- @ranges = parse_ranges(reference.split(/[,;]/))
14
+ def self.book_names
15
+ @@book_names ||= ["Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy", "Joshua", "Judges", "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings", "1 Chronicles", "2 Chronicles", "Ezra", "Nehemiah", "Esther", "Job", "Psalm", "Proverbs", "Ecclesiastes", "Song of Songs", "Isaiah", "Jeremiah", "Lamentations", "Ezekiel", "Daniel", "Hosea", "Joel", "Amos", "Obadiah", "Jonah", "Micah", "Nahum", "Habakkuk", "Zephaniah", "Haggai", "Zechariah", "Malachi", "Matthew", "Mark", "Luke", "John", "Acts", "Romans", "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians", "Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians", "1 Timothy", "2 Timothy", "Titus", "Philemon", "Hebrews", "James", "1 Peter", "2 Peter", "1 John ", "2 John", "3 John", "Jude", "Revelation"]
21
16
  end
22
17
 
23
18
 
24
19
 
25
- def self.book_names
26
- @@book_names ||= ["Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy", "Joshua", "Judges", "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings", "1 Chronicles", "2 Chronicles", "Ezra", "Nehemiah", "Esther", "Job", "Psalm", "Proverbs", "Ecclesiastes", "Song of Songs", "Isaiah", "Jeremiah", "Lamentations", "Ezekiel", "Daniel", "Hosea", "Joel", "Amos", "Obadiah", "Jonah", "Micah", "Nahum", "Habakkuk", "Zephaniah", "Haggai", "Zechariah", "Malachi", "Matthew", "Mark", "Luke", "John", "Acts", "Romans", "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians", "Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians", "1 Timothy", "2 Timothy", "Titus", "Philemon", "Hebrews", "James", "1 Peter", "2 Peter", "1 John ", "2 John", "3 John", "Jude", "Revelation"]
20
+ def initialize(string_or_array)
21
+ case string_or_array
22
+ when String, MatchData
23
+ match = string_or_array.is_a?(String) ? Pericope.match_one(string_or_array) : string_or_array
24
+ raise "no pericope found in #{string_or_array} (#{string_or_array.class})" if match.nil?
25
+
26
+ @original_string = match.to_s
27
+ @index = match.begin(0)
28
+ set_book match.instance_variable_get('@book')
29
+ @ranges = parse_reference(match[1])
30
+
31
+ when Array
32
+ set_book Pericope.get_book(string_or_array.first)
33
+ @ranges = Pericope.group_array_into_ranges(string_or_array)
34
+
35
+ else
36
+ raise ArgumentError, "#{string_or_array.class} is not a recognized input for pericope"
37
+ end
38
+ end
39
+
40
+
41
+
42
+ def book_has_chapters?
43
+ (book_chapter_count > 1)
27
44
  end
28
45
 
29
46
 
@@ -81,7 +98,6 @@ class Pericope
81
98
  pericopes << segment
82
99
  end
83
100
  end
84
- #segments.delete_if {|segment| !segment.is_a?(String)}
85
101
  {:text => text, :pericopes => pericopes}
86
102
  end
87
103
 
@@ -93,13 +109,22 @@ class Pericope
93
109
  if segment.is_a?(String)
94
110
  text << segment
95
111
  else
96
- text << segment.to_a.join(" ")
112
+ text << "{{#{segment.to_a.join(" ")}}}"
97
113
  end
98
114
  end
99
115
  end
100
116
 
101
117
 
102
118
 
119
+ def self.rsub(text)
120
+ text.gsub(/\{\{(\d{7,8} ?)+\}\}/) do |match|
121
+ ids = match[2...-2].split.collect(&:to_i)
122
+ Pericope.new(ids).to_s
123
+ end
124
+ end
125
+
126
+
127
+
103
128
  def to_s
104
129
  "#{book_name} #{self.well_formatted_reference}"
105
130
  end
@@ -138,7 +163,7 @@ class Pericope
138
163
 
139
164
  def well_formatted_reference
140
165
  recent_chapter = nil # e.g. in 12:1-8, remember that 12 is the chapter when we parse the 8
141
- recent_chapter = 1 if !self.book_has_chapters
166
+ recent_chapter = 1 if !self.book_has_chapters?
142
167
  ranges.map do |range|
143
168
  min_chapter = Pericope.get_chapter(range.min)
144
169
  min_verse = Pericope.get_verse(range.min)
@@ -158,9 +183,9 @@ class Pericope
158
183
  recent_chapter = min_chapter
159
184
  s << "#{min_chapter}:#{min_verse}"
160
185
  end
161
-
186
+
162
187
  if range.count > 1
163
-
188
+
164
189
  s << "-"
165
190
  if min_chapter == max_chapter
166
191
  s << max_verse.to_s
@@ -193,12 +218,33 @@ class Pericope
193
218
  def self.get_max_verse(book, chapter)
194
219
  id = (book * 1000000) + (chapter * 1000)
195
220
  chapter_verse_counts[id]
196
- # ActiveRecord::Base.connection.select_value("SELECT verses FROM chapter_verse_count WHERE id=#{id}").to_i
197
221
  end
198
222
 
199
223
 
200
224
 
201
- protected
225
+ private
226
+
227
+
228
+
229
+ def set_book(value)
230
+ @book = value || raise(ArgumentError, "must specify book")
231
+ @book_name = Pericope.book_names[@book-1]
232
+ @book_chapter_count = Pericope.book_chapter_counts[@book-1]
233
+ end
234
+
235
+
236
+
237
+ def parse_reference(reference)
238
+ reference = normalize_reference(reference)
239
+ (reference.nil? || reference.empty?) ? [] : parse_ranges(reference.split(/[,;]/))
240
+ end
241
+
242
+ def normalize_reference(reference)
243
+ { %r{(\d+)[".](\d+)} => '\1:\2', # 12"5 and 12.5 -> 12:5
244
+ %r{[^0-9,:;-]} => '' # remove everything but [0-9,;:-]
245
+ }.each {|pattern, replacement| reference.gsub!(pattern, replacement)}
246
+ reference
247
+ end
202
248
 
203
249
 
204
250
 
@@ -210,6 +256,17 @@ protected
210
256
  get_id(book, chapter, get_max_verse(book, chapter))
211
257
  end
212
258
 
259
+ def self.get_next_verse(id)
260
+ id + 1
261
+ end
262
+
263
+ def self.get_start_of_next_chapter(id)
264
+ book = get_book(id)
265
+ chapter = get_chapter(id) + 1
266
+ verse = 1
267
+ get_id(book, chapter, verse)
268
+ end
269
+
213
270
  def self.get_id(book, chapter, verse) #, constrain_verse=false)
214
271
  book = book.to_i
215
272
  book = 1 if book < 1
@@ -244,12 +301,41 @@ protected
244
301
 
245
302
 
246
303
 
304
+ def self.group_array_into_ranges(array)
305
+ return [] if array.nil? or array.empty?
306
+
307
+ array.flatten!
308
+ array.compact!
309
+ array.sort!
310
+
311
+ ranges = []
312
+ range_start = array.shift
313
+ range_end = range_start
314
+ while true
315
+ next_value = array.shift
316
+ break if next_value.nil?
317
+
318
+ if (next_value == get_next_verse(range_end)) ||
319
+ (next_value == get_start_of_next_chapter(range_end))
320
+ range_end = next_value
321
+ else
322
+ ranges << (range_start..range_end)
323
+ range_start = range_end = next_value
324
+ end
325
+ end
326
+ ranges << (range_start..range_end)
327
+
328
+ ranges
329
+ end
330
+
331
+
332
+
247
333
  # matches the first valid Bible reference in the supplied string
248
334
  def self.match_one(text)
249
335
  match_all(text) do |match|
250
336
  return match
251
337
  end
252
- return nil
338
+ nil
253
339
  end
254
340
 
255
341
 
@@ -267,8 +353,7 @@ protected
267
353
  # after matching "2 Peter" don't match "Peter" again as "1 Peter"
268
354
  # but keep the same number of characters in the string so indices work
269
355
  unmatched = match.pre_match + ("*" * length) + match.post_match
270
- match.instance_variable_set("@book", book[0])
271
- # match = [match, book[0]]
356
+ match.instance_variable_set('@book', book[0])
272
357
  if block_given?
273
358
  yield match
274
359
  else
@@ -283,7 +368,7 @@ protected
283
368
 
284
369
  def parse_ranges(ranges)
285
370
  recent_chapter = nil # e.g. in 12:1-8, remember that 12 is the chapter when we parse the 8
286
- recent_chapter = 1 if !self.book_has_chapters
371
+ recent_chapter = 1 if !self.book_has_chapters?
287
372
  ranges.map do |range|
288
373
  range = range.split('-') # parse the low end of a verse range and the high end separately
289
374
  range << range[0] if (range.length < 2) # treat 12:4 as 12:4-12:4
@@ -348,15 +433,6 @@ protected
348
433
 
349
434
 
350
435
 
351
- def normalize_reference(reference)
352
- { %r{(\d+)[".](\d+)} => '\1:\2', # 12"5 and 12.5 -> 12:5
353
- %r{[^0-9,:;-]} => '' # remove everything but [0-9,;:-]
354
- }.each {|pattern, replacement| reference.gsub!(pattern, replacement)}
355
- reference
356
- end
357
-
358
-
359
-
360
436
  def self.chapter_verse_counts
361
437
  @chapter_verse_counts ||= load_chapter_verse_counts
362
438
  end
data/lib/pericope/cli.rb CHANGED
@@ -6,13 +6,14 @@ class Pericope
6
6
 
7
7
 
8
8
 
9
- ALLOWED_COMMANDS = %w{help normalize parse substitute usage}
9
+ ALLOWED_COMMANDS = %w{help normalize parse substitute reverse-substitute usage}
10
10
 
11
11
 
12
12
 
13
13
  def self.run(command, *args)
14
14
  if ALLOWED_COMMANDS.member?(command)
15
- CLI.new(*args).send(command.to_sym)
15
+ command = command.gsub(/-/, '_').to_sym
16
+ CLI.new(*args).send(command)
16
17
  else
17
18
  CLI.new(*args).usage
18
19
  end
@@ -65,6 +66,16 @@ Glossary
65
66
 
66
67
 
67
68
 
69
+ def reverse_substitute
70
+ begin
71
+ print Pericope.rsub(input)
72
+ rescue
73
+ print $!.to_s
74
+ end
75
+ end
76
+
77
+
78
+
68
79
  def usage
69
80
  print <<-USAGE
70
81
 
@@ -74,11 +85,12 @@ Usage
74
85
 
75
86
  Commands
76
87
 
77
- help Prints more information about pericope
78
- normalize Accepts a pericope and returns a properly-formatted pericope
79
- parse Accepts a pericope and returns a list of verse IDs
80
- substitute Accepts a block of text and replaces all pericopes in the text with verse IDs
81
- usage Prints this message
88
+ help Prints more information about pericope
89
+ normalize Accepts a pericope and returns a properly-formatted pericope
90
+ parse Accepts a pericope and returns a list of verse IDs
91
+ substitute Accepts a block of text and replaces all pericopes in the text with verse IDs
92
+ reverse-substitute Accepts a block of text and replaces collections of verse IDs with pericopes
93
+ usage Prints this message
82
94
 
83
95
  USAGE
84
96
  end
@@ -1,3 +1,3 @@
1
1
  class Pericope
2
- VERSION = "0.5.1" unless defined?(::Pericope::Version)
2
+ VERSION = "0.5.2" unless defined?(::Pericope::Version)
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pericope
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 1
10
- version: 0.5.1
9
+ - 2
10
+ version: 0.5.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bob Lail
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-12 00:00:00 -05:00
18
+ date: 2010-10-26 00:00:00 -05:00
19
19
  default_executable: pericope
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency