-- ***********************************************************************
--
-- Module to display the King James Bible
-- Copyright 2019 by Sean Conner.
--
-- This program is free software: you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the
-- Free Software Foundation, either version 3 of the License, or (at your
-- option) any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details.
--
-- You should have received a copy of the GNU General Public License along
-- with this program. If not, see <
http://www.gnu.org/licenses/>.
--
-- Comments, questions and criticisms can be sent to:
[email protected]
-- ***********************************************************************
-- luacheck: globals handle
-- luacheck: ignore 611
local soundex = require "org.conman.parsers.soundex"
local metaphone = require "org.conman.string".metaphone
local wrapt = require "org.conman.string".wrapt
local CONFIG = require "CONFIG"
local lpeg = require "lpeg"
local io = require "io"
local math = require "math"
local string = require "string"
local table = require "table"
local require = require
local tonumber = tonumber
local _VERSION = _VERSION
if _VERSION == "Lua 5.1" then
module("bible")
else
_ENV = {}
end
-- ***********************************************************************
local ABBR , BOOKS , SOUNDEX , METAPHONE do
local entry = lpeg.C(lpeg.R("AZ","az","09")^1)
* lpeg.S" \t"^0 * lpeg.P"," * lpeg.S" \t"^0
* lpeg.C(lpeg.R("AZ","az","09")^1)
ABBR = {}
BOOKS = {}
SOUNDEX = {}
METAPHONE = {}
for line in io.lines(CONFIG.bible.books) do
local abbr,book = entry:match(line)
local s = soundex:match(book)
local m = metaphone(book)
ABBR[abbr] = book
BOOKS[book] = true
SOUNDEX[s] = book
METAPHONE[m] = book
end
end
-- ***********************************************************************
local parse do
local Cb = lpeg.Cb
local Cc = lpeg.Cc
local Cg = lpeg.Cg
local Ct = lpeg.Ct
local P = lpeg.P
local R = lpeg.R
-- G G.1:1-999:999
-- G.a G.a:1-a:999
-- G.a:b G.a:b-a:b
-- G.a:b-x G.a:b-a:x
-- G.a-c G.a:1-c:999
-- G.a-c:d G.a:1-c:d
-- G.a:b-c:d G.a:b-c:d
local num = R"09"^1 / tonumber
local book = Cg(R("AZ","az","09")^1,'book')
* Cg(Cc( 1),'cb') * Cg(Cc( 1),'vb') -- starting chapter/book
* Cg(Cc(999),'ce') * Cg(Cc(999),'ve') -- ending chapter/book
local start = P"." * Cg(num,'cb')
* Cg(Cb'cb','ce')
* (
P":" * Cg(num,'vb')
* (
(#(P"-" * R"09"^1 * P(-1)) * P"-" * Cg(num,'ve'))
+ Cg(Cb'vb','ve')
)
)^-1
local stop = P"-" * Cg(num,'ce')
* (P":" * Cg(num,'ve'))^-1
parse = Ct(book * (start * stop^-1)^-1)
end
-- ***********************************************************************
local function request(query)
local r = parse:match(query)
if not r then return end
if ABBR[r.book] then
r.book = ABBR[r.book]
return r
end
if not BOOKS[r.book] then
local s = soundex:match(r.book)
if SOUNDEX[s] then
r.book = SOUNDEX[s]
return r
end
local m = metaphone(r.book)
if METAPHONE[m] then
r.book = METAPHONE[m]
return r
end
else
return r
end
end
-- ***********************************************************************
function handle(req)
local handler = require "handler"
local r = request(req)
local bytes = 0
if not r then
return handler.ERROR {
handler.ERROR ,
string.format("%q not found",req),
""
}
end
-- ================================================
local function write(fmt,...)
local s = string.format(fmt,...)
io.stdout:write(s)
bytes = bytes + #s
end
-- ================================================
local function readint(file)
local c = file:read(1) -- trigger EOF
if c then
return c:byte()
+ file:read(1):byte() * 2^8
+ file:read(1):byte() * 2^16
+ file:read(1):byte() * 2^24
end
end
-- ================================================
local function show_chapter(chapter,low,high)
local index = io.open(string.format("%s/%s/%d.index",CONFIG.bible.verses,r.book,chapter),"rb")
if not index then return end
local verse = io.open(string.format("%s/%s/%d",CONFIG.bible.verses,r.book,chapter),"r")
local max = math.min(high,readint(index))
high = math.min(high,max)
index:seek('set',low * 4)
local start = readint(index)
verse:seek('set',start)
local hdr = string.format("Chapter %d",chapter)
write("\n%s%s\n\n",string.rep(" ",40 - #hdr / 2),hdr)
for v = low , high do
local stop = readint(index)
local len = stop - start
local text = verse:read(len)
local wt = wrapt(text,60)
start = stop
write("%3d. %s\n",v,table.concat(wt,"\n "))
end
index:close()
verse:close()
end
-- ================================================
write("%s%s\n",string.rep(" ",40 - #r.book / 2),r.book)
for chapter = r.cb , r.ce do
local vb
local ve
if chapter == r.cb then
vb = r.vb
else
vb = 1
end
if chapter == r.ce then
ve = r.ve
else
ve = 999
end
show_chapter(chapter,vb,ve)
end
return bytes
end
-- ***********************************************************************
if _VERSION >= "Lua 5.2" then
return _ENV
end