Add private MEV embedded support
This commit is contained in:
+6
-3
@@ -9,6 +9,7 @@ import cliutils, docopt, zero_functional
|
||||
import ./api_bible
|
||||
import ./esv
|
||||
import ./kjv
|
||||
import ./mev
|
||||
|
||||
proc formatMarkdown(raw, translation: string): string =
|
||||
var reference = ""
|
||||
@@ -80,6 +81,8 @@ proc fetchPassages(reference, translation: string, cfg: CombinedConfig): seq[str
|
||||
cfg.getVal("esv-api-root", "https://api.esv.org"))
|
||||
of "akjv", "kjv":
|
||||
kjv.fetchPassages(reference)
|
||||
of "mev":
|
||||
mev.fetchPassages(reference)
|
||||
of "amp", "nkjv", "niv":
|
||||
api_bible.fetchPassages(
|
||||
reference,
|
||||
@@ -92,7 +95,7 @@ proc fetchPassages(reference, translation: string, cfg: CombinedConfig): seq[str
|
||||
else:
|
||||
raise newException(ValueError,
|
||||
"unsupported translation '" & translation &
|
||||
"'; supported translations: akjv, amp, esv, kjv, nkjv, niv")
|
||||
"'; supported translations: akjv, amp, esv, kjv, mev, nkjv, niv")
|
||||
|
||||
when isMainModule:
|
||||
const USAGE = """Usage:
|
||||
@@ -110,8 +113,8 @@ Options:
|
||||
|
||||
-t, --translation <translation>
|
||||
Select a specific translation. Supported values
|
||||
are 'akjv', 'amp', 'esv', 'kjv', 'nkjv', and
|
||||
'niv'. Defaults to 'esv'.
|
||||
are 'akjv', 'amp', 'esv', 'kjv', 'mev',
|
||||
'nkjv', and 'niv'. Defaults to 'esv'.
|
||||
|
||||
--esv-api-token <token> Provide the API token on the command line. By
|
||||
default this will be read either from the
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import std/[strutils, tables]
|
||||
|
||||
import ./reference_parser
|
||||
|
||||
type BibleIndex = object
|
||||
verses: Table[string, string]
|
||||
lastVerseByChapter: Table[string, int]
|
||||
lastChapterByBook: Table[string, int]
|
||||
translationName: string
|
||||
|
||||
proc verseKey(code: string, chapter, verse: int): string =
|
||||
code & "\t" & $chapter & "\t" & $verse
|
||||
|
||||
proc chapterKey(code: string, chapter: int): string =
|
||||
code & "\t" & $chapter
|
||||
|
||||
proc loadBibleIndex(rows, translationName: string): BibleIndex =
|
||||
result.translationName = translationName
|
||||
|
||||
for line in rows.splitLines:
|
||||
if line.strip.len == 0:
|
||||
continue
|
||||
|
||||
let parts = line.split('\t', maxsplit = 3)
|
||||
if parts.len != 4:
|
||||
raise newException(ValueError,
|
||||
"invalid embedded " & translationName & " row: " & line)
|
||||
|
||||
let code = parts[0]
|
||||
let chapter = parseInt(parts[1])
|
||||
let verse = parseInt(parts[2])
|
||||
let text = parts[3]
|
||||
|
||||
result.verses[verseKey(code, chapter, verse)] = text
|
||||
|
||||
let cKey = chapterKey(code, chapter)
|
||||
if not result.lastVerseByChapter.hasKey(cKey) or
|
||||
verse > result.lastVerseByChapter[cKey]:
|
||||
result.lastVerseByChapter[cKey] = verse
|
||||
|
||||
if not result.lastChapterByBook.hasKey(code) or
|
||||
chapter > result.lastChapterByBook[code]:
|
||||
result.lastChapterByBook[code] = chapter
|
||||
|
||||
proc requireLastChapter(index: BibleIndex, code: string): int =
|
||||
if not index.lastChapterByBook.hasKey(code):
|
||||
raise newException(ValueError,
|
||||
"no embedded " & index.translationName & " data for " & code)
|
||||
index.lastChapterByBook[code]
|
||||
|
||||
proc requireLastVerse(index: BibleIndex, code: string, chapter: int): int =
|
||||
let cKey = chapterKey(code, chapter)
|
||||
if not index.lastVerseByChapter.hasKey(cKey):
|
||||
raise newException(ValueError,
|
||||
"no embedded " & index.translationName & " data for " &
|
||||
bookInfo(code).name & " " & $chapter)
|
||||
index.lastVerseByChapter[cKey]
|
||||
|
||||
proc requireVerse(index: BibleIndex, code: string, chapter, verse: int): string =
|
||||
let vKey = verseKey(code, chapter, verse)
|
||||
if not index.verses.hasKey(vKey):
|
||||
raise newException(ValueError,
|
||||
"no embedded " & index.translationName & " data for " &
|
||||
bookInfo(code).name & " " & $chapter & ":" & $verse)
|
||||
index.verses[vKey]
|
||||
|
||||
proc addVerseLines(
|
||||
lines: var seq[string],
|
||||
index: BibleIndex,
|
||||
reference: PassageReference,
|
||||
range: RefRange) =
|
||||
|
||||
let code = reference.book.code
|
||||
discard index.requireLastChapter(code)
|
||||
|
||||
for chapter in range.start.chapter .. range.finish.chapter:
|
||||
let startVerse =
|
||||
if chapter == range.start.chapter and range.start.verse > 0:
|
||||
range.start.verse
|
||||
else:
|
||||
1
|
||||
|
||||
let endVerse =
|
||||
if chapter == range.finish.chapter and range.finish.verse > 0:
|
||||
range.finish.verse
|
||||
else:
|
||||
index.requireLastVerse(code, chapter)
|
||||
|
||||
if startVerse > endVerse:
|
||||
raise newException(ValueError, "reference range starts after it ends")
|
||||
|
||||
for verse in startVerse .. endVerse:
|
||||
lines.add(" [" & $verse & "] " & index.requireVerse(code, chapter, verse))
|
||||
|
||||
proc fetchReference(index: BibleIndex, reference: PassageReference): string =
|
||||
var lines = @[$reference]
|
||||
let code = reference.book.code
|
||||
|
||||
if reference.ranges.len == 0:
|
||||
for chapter in 1 .. index.requireLastChapter(code):
|
||||
for verse in 1 .. index.requireLastVerse(code, chapter):
|
||||
lines.add(" [" & $verse & "] " & index.requireVerse(code, chapter, verse))
|
||||
else:
|
||||
for range in reference.ranges:
|
||||
lines.addVerseLines(index, reference, range)
|
||||
|
||||
lines.join("\n")
|
||||
|
||||
proc fetchPassages*(rows, reference, translationName: string): seq[string] =
|
||||
let index = loadBibleIndex(rows, translationName)
|
||||
for parsedReference in parseReferences(reference):
|
||||
result.add(fetchReference(index, parsedReference))
|
||||
+2
-104
@@ -1,109 +1,7 @@
|
||||
import std/[strutils, tables]
|
||||
|
||||
import ./embedded_bible
|
||||
import ./offline_data
|
||||
import ./reference_parser
|
||||
|
||||
const kjvRows = embeddedTranslationData("kjv")
|
||||
|
||||
type BibleIndex = object
|
||||
verses: Table[string, string]
|
||||
lastVerseByChapter: Table[string, int]
|
||||
lastChapterByBook: Table[string, int]
|
||||
|
||||
proc verseKey(code: string, chapter, verse: int): string =
|
||||
code & "\t" & $chapter & "\t" & $verse
|
||||
|
||||
proc chapterKey(code: string, chapter: int): string =
|
||||
code & "\t" & $chapter
|
||||
|
||||
proc loadBibleIndex(): BibleIndex =
|
||||
for line in kjvRows.splitLines:
|
||||
if line.strip.len == 0:
|
||||
continue
|
||||
|
||||
let parts = line.split('\t', maxsplit = 3)
|
||||
if parts.len != 4:
|
||||
raise newException(ValueError, "invalid embedded KJV row: " & line)
|
||||
|
||||
let code = parts[0]
|
||||
let chapter = parseInt(parts[1])
|
||||
let verse = parseInt(parts[2])
|
||||
let text = parts[3]
|
||||
|
||||
result.verses[verseKey(code, chapter, verse)] = text
|
||||
|
||||
let cKey = chapterKey(code, chapter)
|
||||
if not result.lastVerseByChapter.hasKey(cKey) or
|
||||
verse > result.lastVerseByChapter[cKey]:
|
||||
result.lastVerseByChapter[cKey] = verse
|
||||
|
||||
if not result.lastChapterByBook.hasKey(code) or
|
||||
chapter > result.lastChapterByBook[code]:
|
||||
result.lastChapterByBook[code] = chapter
|
||||
|
||||
proc requireLastChapter(index: BibleIndex, code: string): int =
|
||||
if not index.lastChapterByBook.hasKey(code):
|
||||
raise newException(ValueError, "no embedded KJV data for " & code)
|
||||
index.lastChapterByBook[code]
|
||||
|
||||
proc requireLastVerse(index: BibleIndex, code: string, chapter: int): int =
|
||||
let cKey = chapterKey(code, chapter)
|
||||
if not index.lastVerseByChapter.hasKey(cKey):
|
||||
raise newException(ValueError,
|
||||
"no embedded KJV data for " & bookInfo(code).name & " " & $chapter)
|
||||
index.lastVerseByChapter[cKey]
|
||||
|
||||
proc requireVerse(index: BibleIndex, code: string, chapter, verse: int): string =
|
||||
let vKey = verseKey(code, chapter, verse)
|
||||
if not index.verses.hasKey(vKey):
|
||||
raise newException(ValueError,
|
||||
"no embedded KJV data for " & bookInfo(code).name & " " &
|
||||
$chapter & ":" & $verse)
|
||||
index.verses[vKey]
|
||||
|
||||
proc addVerseLines(
|
||||
lines: var seq[string],
|
||||
index: BibleIndex,
|
||||
reference: PassageReference,
|
||||
range: RefRange) =
|
||||
|
||||
let code = reference.book.code
|
||||
discard index.requireLastChapter(code)
|
||||
|
||||
for chapter in range.start.chapter .. range.finish.chapter:
|
||||
let startVerse =
|
||||
if chapter == range.start.chapter and range.start.verse > 0:
|
||||
range.start.verse
|
||||
else:
|
||||
1
|
||||
|
||||
let endVerse =
|
||||
if chapter == range.finish.chapter and range.finish.verse > 0:
|
||||
range.finish.verse
|
||||
else:
|
||||
index.requireLastVerse(code, chapter)
|
||||
|
||||
if startVerse > endVerse:
|
||||
raise newException(ValueError, "reference range starts after it ends")
|
||||
|
||||
for verse in startVerse .. endVerse:
|
||||
lines.add(" [" & $verse & "] " & index.requireVerse(code, chapter, verse))
|
||||
|
||||
proc fetchReference(index: BibleIndex, reference: PassageReference): string =
|
||||
var lines = @[$reference]
|
||||
let code = reference.book.code
|
||||
|
||||
if reference.ranges.len == 0:
|
||||
for chapter in 1 .. index.requireLastChapter(code):
|
||||
for verse in 1 .. index.requireLastVerse(code, chapter):
|
||||
lines.add(" [" & $verse & "] " & index.requireVerse(code, chapter, verse))
|
||||
else:
|
||||
for range in reference.ranges:
|
||||
lines.addVerseLines(index, reference, range)
|
||||
|
||||
lines.join("\n")
|
||||
|
||||
proc fetchPassages*(reference: string): seq[string] =
|
||||
let index = loadBibleIndex()
|
||||
for parsedReference in parseReferences(reference):
|
||||
result.add(fetchReference(index, parsedReference))
|
||||
embedded_bible.fetchPassages(kjvRows, reference, "KJV")
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import ./offline_data
|
||||
|
||||
when hasEmbeddedTranslationData("mev"):
|
||||
import ./embedded_bible
|
||||
|
||||
const mevRows = embeddedTranslationData("mev")
|
||||
|
||||
proc fetchPassages*(reference: string): seq[string] =
|
||||
when hasEmbeddedTranslationData("mev"):
|
||||
embedded_bible.fetchPassages(mevRows, reference, "MEV")
|
||||
else:
|
||||
raise newException(ValueError,
|
||||
"MEV data is not embedded; generate data/private/mev.tsv and rebuild")
|
||||
+10
-6
@@ -1,11 +1,15 @@
|
||||
import std/os
|
||||
|
||||
template embeddedTranslationData*(name: static[string]): string =
|
||||
template translationDataPath(name: static[string], visibility: static[string]): string =
|
||||
const dataRoot = currentSourcePath().parentDir.parentDir / "data"
|
||||
const privatePath = dataRoot / "private" / (name & ".tsv")
|
||||
const publicPath = dataRoot / "public" / (name & ".tsv")
|
||||
dataRoot / visibility / (name & ".tsv")
|
||||
|
||||
when fileExists(privatePath):
|
||||
staticRead(privatePath)
|
||||
template hasEmbeddedTranslationData*(name: static[string]): bool =
|
||||
fileExists(translationDataPath(name, "private")) or
|
||||
fileExists(translationDataPath(name, "public"))
|
||||
|
||||
template embeddedTranslationData*(name: static[string]): string =
|
||||
when fileExists(translationDataPath(name, "private")):
|
||||
staticRead(translationDataPath(name, "private"))
|
||||
else:
|
||||
staticRead(publicPath)
|
||||
staticRead(translationDataPath(name, "public"))
|
||||
|
||||
Reference in New Issue
Block a user