201 lines
5.5 KiB
Rust
201 lines
5.5 KiB
Rust
use std::{fmt::Display, fs::read_to_string};
|
|
use inline_colorization::*;
|
|
|
|
use quick_xml::de::from_str;
|
|
use serde::Deserialize;
|
|
|
|
pub fn get(query: &str) -> Option<Entry> {
|
|
// TODO Put this in a singleton
|
|
let file = read_to_string("/usr/local/bible/HebrewStrong.xml").expect("Failed to get the strong xml file. It's expect to be at:\n/usr/local/bible/HebrewString.xml\n\n");
|
|
let obj: HebrewStrong = from_str(&file).unwrap();
|
|
|
|
// Yes, dumb search is ok. Searching for the last element took 2ms
|
|
obj.entries.into_iter().find(|entry| entry.number.eq(&query))
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct HebrewStrong {
|
|
#[serde(rename = "$value")]
|
|
pub entries: Vec<Entry>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
pub struct Entry {
|
|
#[serde(rename = "@id")]
|
|
pub number: String,
|
|
w: Word,
|
|
// TODO find who has multiple notes
|
|
note: Option<Vec<Note>>,
|
|
source: Option<Source>,
|
|
meaning: Option<Meaning>,
|
|
usage: Option<Usage>,
|
|
}
|
|
impl Display for Entry {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
writeln!(f, "{color_red}Strong's ID{style_reset}: {}", self.number)?;
|
|
|
|
if let Some(notes) = &self.note {
|
|
write!(f, "Notes:")?;
|
|
for note in notes {
|
|
writeln!(f, "{}", note)?;
|
|
}
|
|
}
|
|
|
|
write!(f, "{}", self.w)?;
|
|
|
|
if let Some(i) = &self.source {
|
|
writeln!(f, "{}", i)?;
|
|
}
|
|
|
|
if let Some(i) = &self.meaning {
|
|
writeln!(f, "{}", i)?;
|
|
}
|
|
|
|
if let Some(i) = &self.usage {
|
|
writeln!(f, "{}", i)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Word {
|
|
#[serde(rename = "@pos")]
|
|
// TODO this is actaully a link to PartsOfSpeech.xml
|
|
part_of_speech: Option<String>,
|
|
|
|
#[serde(rename = "@pron")]
|
|
pronunciation: Option<String>,
|
|
|
|
#[serde(rename = "@xlit")]
|
|
transliteration: Option<String>,
|
|
|
|
#[serde(rename = "@xlm:lang")]
|
|
lang: Option<String>,
|
|
|
|
#[serde(rename = "$value")]
|
|
inner: String,
|
|
|
|
#[serde(rename = "@src")]
|
|
links_to: Option<String>,
|
|
}
|
|
impl Display for Word {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(part_of_speech) = &self.part_of_speech {
|
|
writeln!(f, "{color_magenta}Part of speech{style_reset}: {}", part_of_speech)?;
|
|
}
|
|
|
|
if let Some(i) = &self.transliteration {
|
|
writeln!(f, "{color_green}Transliteration{style_reset}: {}", i)?;
|
|
}
|
|
|
|
if let Some(i) = &self.lang {
|
|
writeln!(f, "{color_red}Language{style_reset}: {}", i)?;
|
|
}
|
|
|
|
writeln!(f, "{color_bright_cyan}Writen{style_reset}: {}", self.inner)?;
|
|
|
|
if let Some(pron) = &self.pronunciation {
|
|
writeln!(f, "{color_yellow}Pronounciation{style_reset}: {}", pron)?;
|
|
}
|
|
|
|
if let Some(i) = &self.links_to {
|
|
writeln!(f, "{color_bright_green}Also see{style_reset}: {}", i)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Note {
|
|
#[serde(rename = "$value")]
|
|
inner: String,
|
|
}
|
|
impl Display for Note {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.inner)
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Source {
|
|
#[serde(rename = "$value")]
|
|
// Text vs Words make this a vec
|
|
inner: Option<Vec<MixedText>>,
|
|
}
|
|
impl Display for Source {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(inner) = &self.inner {
|
|
// WE ARE LOOPING
|
|
// !! Don't use writeln
|
|
write!(f, "{color_bright_green}Source{style_reset}: ")?;
|
|
for i in inner {
|
|
match i {
|
|
MixedText::Word(word) => {
|
|
if let Some(i) = &word.links_to {
|
|
write!(f, "{style_bold} (See: {}){style_reset}", i)?;
|
|
}
|
|
write!(f, "{color_bright_white} {} {style_reset}", word.inner)?;
|
|
},
|
|
_ => write!(f, "{}", i)?,
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Meaning {
|
|
#[serde(rename = "$value")]
|
|
inner: Vec<MixedText>,
|
|
}
|
|
impl Display for Meaning {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{color_cyan}Meaning:{style_reset}")?;
|
|
for i in &self.inner {
|
|
write!(f, "{}", i)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Usage {
|
|
#[serde(rename = "$value")]
|
|
inner: Vec<String>,
|
|
}
|
|
impl Display for Usage {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let new = self.inner.join(" ");
|
|
write!(f, "{color_bright_magenta}Usage{style_reset}: {new}")
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
enum MixedText {
|
|
#[serde(rename = "w")]
|
|
Word(Word),
|
|
#[serde(rename = "$text")]
|
|
Text(String),
|
|
#[serde(rename = "def")]
|
|
/// The actual definition, as opposed to the supporting `MixedText::Text`, which is just
|
|
/// supporting text elements.
|
|
Definition(String),
|
|
#[serde(rename = "note")]
|
|
Note(Note),
|
|
}
|
|
impl Display for MixedText {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
MixedText::Word(word) => write!(f, "{}", word),
|
|
MixedText::Text(text) => write!(f, "{}", text),
|
|
MixedText::Definition(def) => write!(f, " {style_bold}{}{style_reset} ", def),
|
|
MixedText::Note(note) => write!(f, "{}", note),
|
|
}
|
|
}
|
|
}
|
|
|