support for multiple bibles at the same time
This commit is contained in:
parent
d26c02d239
commit
c2e985e10a
132
src/bible.rs
132
src/bible.rs
@ -1,5 +1,5 @@
|
|||||||
use std::{fmt::Display, fs::read_to_string};
|
|
||||||
use inline_colorization::*;
|
use inline_colorization::*;
|
||||||
|
use std::{fmt::Display, fs};
|
||||||
|
|
||||||
use quick_xml::de::from_str;
|
use quick_xml::de::from_str;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@ -73,12 +73,24 @@ const BOOKS_IN_ORDER: [&str; 66] = [
|
|||||||
"Revelation",
|
"Revelation",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// This would eventaully be a list built by the user
|
||||||
|
const BIBLES: [&str; 2] = [
|
||||||
|
"/usr/local/bible/EnglishNASBBible.xml",
|
||||||
|
"/usr/local/bible/EnglishNIVBible.xml",
|
||||||
|
];
|
||||||
|
|
||||||
pub fn get(query: &str, loc: &str) {
|
pub fn get(query: &str, loc: &str) {
|
||||||
// expecting query to be in format:
|
// expecting query to be in format:
|
||||||
// Gen 1:2
|
// Gen 1:2
|
||||||
// Gen 1:2-5
|
// Gen 1:2-5
|
||||||
// Genesis 1
|
// Gen 1
|
||||||
|
// The book name needs to be just long enough to be unique
|
||||||
|
|
||||||
|
let mut splits = loc.split(':');
|
||||||
|
let chapter = splits.next();
|
||||||
|
let verse = splits.next();
|
||||||
|
|
||||||
|
// ###########################################
|
||||||
// Figure out what book they are talking about
|
// Figure out what book they are talking about
|
||||||
let res = BOOKS_IN_ORDER
|
let res = BOOKS_IN_ORDER
|
||||||
.iter()
|
.iter()
|
||||||
@ -86,7 +98,7 @@ pub fn get(query: &str, loc: &str) {
|
|||||||
.filter(|(_, book)| book.to_lowercase().contains(&query.to_lowercase()))
|
.filter(|(_, book)| book.to_lowercase().contains(&query.to_lowercase()))
|
||||||
.collect::<Vec<(usize, &&str)>>();
|
.collect::<Vec<(usize, &&str)>>();
|
||||||
|
|
||||||
let found_book = match res.len() {
|
let (book_idx, book_name) = match res.len() {
|
||||||
1 => res[0],
|
1 => res[0],
|
||||||
2.. => {
|
2.. => {
|
||||||
eprintln!("Err: Ambigious input '{query}', could be any of:");
|
eprintln!("Err: Ambigious input '{query}', could be any of:");
|
||||||
@ -101,53 +113,90 @@ pub fn get(query: &str, loc: &str) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = read_to_string("/usr/local/bible/EnglishNASBBible.xml").expect(
|
// Load Bibles into memory
|
||||||
"Failed to get the bible xml file. It's expect to be at:\n/usr/local/bible/<name>.xml\n\n",
|
let bibles = BIBLES
|
||||||
);
|
.iter()
|
||||||
let bible: Bible = from_str(&file).unwrap();
|
.filter_map(|path| fs::read_to_string(path).ok())
|
||||||
|
.filter_map(|contents| from_str::<Bible>(&contents).ok())
|
||||||
|
.collect::<Vec<Bible>>();
|
||||||
|
// Select the book in each Bible
|
||||||
|
let books = bibles
|
||||||
|
.iter()
|
||||||
// Book are 1 indexed in the xml spec
|
// Book are 1 indexed in the xml spec
|
||||||
if let Some(book) = bible.get_book_by_index(found_book.0 + 1) {
|
.map(|bible| (bible, bible.get_book_by_index(book_idx + 1)))
|
||||||
// Figure out what verse they want
|
.filter(|(_,e)| e.is_some())
|
||||||
let mut splits = loc.split(':');
|
.map(|(bible,book)| (bible,book.unwrap()))
|
||||||
let chatper = splits.next();
|
.collect::<Vec<(&Bible,&Book)>>();
|
||||||
let verse = splits.next();
|
|
||||||
|
|
||||||
|
// Select the chapter in each Bible
|
||||||
if let Some(chapter) = chatper {
|
let chapters = if let Some(chapter) = chapter {
|
||||||
if let Ok(chap_num) = chapter.trim().parse::<usize>() {
|
if let Ok(ch_num) = chapter.parse::<usize>() {
|
||||||
if let Some(chapter) = book.get_chapter_by_index(chap_num) {
|
books
|
||||||
if let Some(verse) = verse {
|
.iter()
|
||||||
if let Ok(verse_num) = verse.trim().parse::<usize>() {
|
.map(|(bible,book)| (bible, book, book.get_chapter_by_index(ch_num)))
|
||||||
// return specific verse
|
.filter(|(_,_,book)| book.is_some())
|
||||||
if let Some(verse) = chapter.get_verse_by_index(verse_num) {
|
.map(|(bible,book,chapter)| (*bible,*book,chapter.unwrap()))
|
||||||
println!("{style_underline}{style_bold}{} {}:{}{style_reset}: {}", found_book.1, chapter.number, verse.number, verse);
|
.collect::<Vec<(&Bible, &Book, &Chapter)>>()
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// might have input a verse range
|
return;
|
||||||
let range: Vec<&str> = verse.split("-").collect();
|
};
|
||||||
if range.len() == 2 {
|
|
||||||
let start = range[0].parse::<usize>();
|
|
||||||
let end = range[1].parse::<usize>();
|
|
||||||
|
|
||||||
if let (Ok(s), Ok(e)) = (start,end) {
|
// Get the verse in each Bible
|
||||||
println!("{style_underline}{style_bold}{} {}:{}-{}{style_reset}:", found_book.1, chapter.number, s, e);
|
match verse {
|
||||||
for verse_idx in s..=e {
|
Some(verse) => {
|
||||||
if let Some(v) = chapter.get_verse_by_index(verse_idx) {
|
let mut splits = verse.split("-");
|
||||||
println!("{style_underline}{style_bold}{}{style_reset}: {}", v.number, v);
|
let start = splits.next();
|
||||||
|
let end = splits.next();
|
||||||
|
|
||||||
|
match (start, end) {
|
||||||
|
// range of verses
|
||||||
|
(Some(sn), Some(en)) => {
|
||||||
|
if let (Ok(start), Ok(end)) = (sn.parse::<usize>(), en.parse::<usize>()) {
|
||||||
|
for num in start..=end {
|
||||||
|
for (bible, _book, chapter) in &chapters {
|
||||||
|
if let Some(verse) = chapter.get_verse_by_index(num) {
|
||||||
|
println!(
|
||||||
|
"{style_bold}[{}] {style_underline}{book_name} {}:{}{style_reset}: {verse}",
|
||||||
|
bible.translation_name, chapter.number, verse.number
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
// only one verse
|
||||||
println!("{style_bold}{style_underline}{} {}{style_reset}:", found_book.1, chapter.number);
|
(Some(ver_num), None) => {
|
||||||
|
if let Ok(num) = ver_num.parse::<usize>() {
|
||||||
|
for (bible, _book, chapter) in chapters {
|
||||||
|
if let Some(verse) = chapter.get_verse_by_index(num) {
|
||||||
|
println!(
|
||||||
|
"{style_bold}[{}] {style_underline}{book_name} {}:{}{style_reset}: {verse}",
|
||||||
|
bible.translation_name, chapter.number, verse.number
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// couldn't parse verse
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// only chapter
|
||||||
|
for (bible, _book, chapter) in chapters {
|
||||||
|
println!(
|
||||||
|
"{style_bold}[{}] {style_underline}{book_name} {}{style_reset}:",
|
||||||
|
bible.translation_name, chapter.number
|
||||||
|
);
|
||||||
print!("{}", chapter);
|
print!("{}", chapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bible {
|
impl Bible {
|
||||||
@ -178,7 +227,7 @@ impl Chapter {
|
|||||||
fn get_verse_by_index(&self, idx: usize) -> Option<&Verse> {
|
fn get_verse_by_index(&self, idx: usize) -> Option<&Verse> {
|
||||||
for verse in &self.verses {
|
for verse in &self.verses {
|
||||||
if verse.number == idx {
|
if verse.number == idx {
|
||||||
return Some(&verse)
|
return Some(&verse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -188,7 +237,7 @@ impl Chapter {
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Bible {
|
struct Bible {
|
||||||
#[serde(rename = "@translation")]
|
#[serde(rename = "@translation")]
|
||||||
_version: String,
|
translation_name: String,
|
||||||
#[serde(rename = "testament")]
|
#[serde(rename = "testament")]
|
||||||
testaments: Vec<Testament>,
|
testaments: Vec<Testament>,
|
||||||
}
|
}
|
||||||
@ -220,7 +269,11 @@ struct Chapter {
|
|||||||
impl Display for Chapter {
|
impl Display for Chapter {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
for v in &self.verses {
|
for v in &self.verses {
|
||||||
writeln!(f, "{style_bold}{style_underline}{}{style_reset}: {}", v.number, v)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{style_bold}{style_underline}{}{style_reset}: {}",
|
||||||
|
v.number, v
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -238,4 +291,3 @@ impl Display for Verse {
|
|||||||
write!(f, "{}", self.text)
|
write!(f, "{}", self.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user